pktools  2.6.3
Processing Kernel for geospatial data
Filter.cc
1 /**********************************************************************
2 Filter.cc: class for filtering
3 Copyright (C) 2008-2012 Pieter Kempeneers
4 
5 This file is part of pktools
6 
7 pktools is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 pktools is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with pktools. If not, see <http://www.gnu.org/licenses/>.
19 ***********************************************************************/
20 #include "Filter.h"
21 #include <assert.h>
22 #include <math.h>
23 #include <iostream>
24 
25 using namespace std;
26 
27 filter::Filter::Filter(void)
28  : m_padding("symmetric")
29 {
30 }
31 
32 
33 filter::Filter::Filter(const vector<double> &taps)
34  : m_padding("symmetric")
35 {
36  setTaps(taps);
37 }
38 
39 void filter::Filter::setTaps(const vector<double> &taps, bool normalize)
40 {
41  m_taps.resize(taps.size());
42  double norm=0;
43  for(int itap=0;itap<taps.size();++itap)
44  norm+=taps[itap];
45  if(norm){
46  for(int itap=0;itap<taps.size();++itap)
47  m_taps[itap]=taps[itap]/norm;
48  }
49  else
50  m_taps=taps;
51  assert(m_taps.size()%2);
52 }
53 
54 int filter::Filter::pushNoDataValue(double noDataValue)
55 {
56  if(find(m_noDataValues.begin(),m_noDataValues.end(),noDataValue)==m_noDataValues.end())
57  m_noDataValues.push_back(noDataValue);
58  return(m_noDataValues.size());
59 }
60 
61 void filter::Filter::dwtForward(const ImgReaderGdal& input, ImgWriterGdal& output, const std::string& wavelet_type, int family){
62  const char* pszMessage;
63  void* pProgressArg=NULL;
64  GDALProgressFunc pfnProgress=GDALTermProgress;
65  double progress=0;
66  pfnProgress(progress,pszMessage,pProgressArg);
67  Vector2d<double> lineInput(input.nrOfBand(),input.nrOfCol());
68  Vector2d<double> lineOutput(input.nrOfBand(),input.nrOfCol());
69  for(int y=0;y<input.nrOfRow();++y){
70  for(int iband=0;iband<input.nrOfBand();++iband)
71  input.readData(lineInput[iband],GDT_Float64,y,iband);
72  vector<double> pixelInput(input.nrOfBand());
73  for(int x=0;x<input.nrOfCol();++x){
74  pixelInput=lineInput.selectCol(x);
75  dwtForward(pixelInput,wavelet_type,family);
76  for(int iband=0;iband<input.nrOfBand();++iband)
77  lineOutput[iband][x]=pixelInput[iband];
78  }
79  for(int iband=0;iband<input.nrOfBand();++iband){
80  try{
81  output.writeData(lineOutput[iband],GDT_Float64,y,iband);
82  }
83  catch(string errorstring){
84  cerr << errorstring << "in band " << iband << ", line " << y << endl;
85  }
86  }
87  progress=(1.0+y)/output.nrOfRow();
88  pfnProgress(progress,pszMessage,pProgressArg);
89  }
90 }
91 
92 void filter::Filter::dwtInverse(const ImgReaderGdal& input, ImgWriterGdal& output, const std::string& wavelet_type, int family){
93  const char* pszMessage;
94  void* pProgressArg=NULL;
95  GDALProgressFunc pfnProgress=GDALTermProgress;
96  double progress=0;
97  pfnProgress(progress,pszMessage,pProgressArg);
98  Vector2d<double> lineInput(input.nrOfBand(),input.nrOfCol());
99  Vector2d<double> lineOutput(input.nrOfBand(),input.nrOfCol());
100  for(int y=0;y<input.nrOfRow();++y){
101  for(int iband=0;iband<input.nrOfBand();++iband)
102  input.readData(lineInput[iband],GDT_Float64,y,iband);
103  vector<double> pixelInput(input.nrOfBand());
104  for(int x=0;x<input.nrOfCol();++x){
105  pixelInput=lineInput.selectCol(x);
106  dwtInverse(pixelInput,wavelet_type,family);
107  for(int iband=0;iband<input.nrOfBand();++iband)
108  lineOutput[iband][x]=pixelInput[iband];
109  }
110  for(int iband=0;iband<input.nrOfBand();++iband){
111  try{
112  output.writeData(lineOutput[iband],GDT_Float64,y,iband);
113  }
114  catch(string errorstring){
115  cerr << errorstring << "in band " << iband << ", line " << y << endl;
116  }
117  }
118  progress=(1.0+y)/output.nrOfRow();
119  pfnProgress(progress,pszMessage,pProgressArg);
120  }
121 }
122 
123 void filter::Filter::dwtCut(const ImgReaderGdal& input, ImgWriterGdal& output, const std::string& wavelet_type, int family, double cut){
124  const char* pszMessage;
125  void* pProgressArg=NULL;
126  GDALProgressFunc pfnProgress=GDALTermProgress;
127  double progress=0;
128  pfnProgress(progress,pszMessage,pProgressArg);
129  Vector2d<double> lineInput(input.nrOfBand(),input.nrOfCol());
130  Vector2d<double> lineOutput(input.nrOfBand(),input.nrOfCol());
131  for(int y=0;y<input.nrOfRow();++y){
132  for(int iband=0;iband<input.nrOfBand();++iband)
133  input.readData(lineInput[iband],GDT_Float64,y,iband);
134  vector<double> pixelInput(input.nrOfBand());
135  for(int x=0;x<input.nrOfCol();++x){
136  pixelInput=lineInput.selectCol(x);
137  dwtCut(pixelInput,wavelet_type,family,cut);
138  for(int iband=0;iband<input.nrOfBand();++iband)
139  lineOutput[iband][x]=pixelInput[iband];
140  }
141  for(int iband=0;iband<input.nrOfBand();++iband){
142  try{
143  output.writeData(lineOutput[iband],GDT_Float64,y,iband);
144  }
145  catch(string errorstring){
146  cerr << errorstring << "in band " << iband << ", line " << y << endl;
147  }
148  }
149  progress=(1.0+y)/output.nrOfRow();
150  pfnProgress(progress,pszMessage,pProgressArg);
151  }
152 }
153 
154 void filter::Filter::dwtCutFrom(const ImgReaderGdal& input, ImgWriterGdal& output, const std::string& wavelet_type, int family, int band){
155  const char* pszMessage;
156  void* pProgressArg=NULL;
157  GDALProgressFunc pfnProgress=GDALTermProgress;
158  double progress=0;
159  pfnProgress(progress,pszMessage,pProgressArg);
160  Vector2d<double> lineInput(input.nrOfBand(),input.nrOfCol());
161  Vector2d<double> lineOutput(input.nrOfBand(),input.nrOfCol());
162  for(int y=0;y<input.nrOfRow();++y){
163  for(int iband=0;iband<input.nrOfBand();++iband)
164  input.readData(lineInput[iband],GDT_Float64,y,iband);
165  vector<double> pixelInput(input.nrOfBand());
166  for(int x=0;x<input.nrOfCol();++x){
167  pixelInput=lineInput.selectCol(x);
168  dwtForward(pixelInput,wavelet_type,family);
169  for(int iband=0;iband<input.nrOfBand();++iband){
170  if(iband>=band)
171  pixelInput[iband]=0;
172  }
173  dwtInverse(pixelInput,wavelet_type,family);
174  for(int iband=0;iband<input.nrOfBand();++iband)
175  lineOutput[iband][x]=pixelInput[iband];
176  }
177  for(int iband=0;iband<input.nrOfBand();++iband){
178  try{
179  output.writeData(lineOutput[iband],GDT_Float64,y,iband);
180  }
181  catch(string errorstring){
182  cerr << errorstring << "in band " << iband << ", line " << y << endl;
183  }
184  }
185  progress=(1.0+y)/output.nrOfRow();
186  pfnProgress(progress,pszMessage,pProgressArg);
187  }
188 }
189 
190 //todo: support different padding strategies
191 void filter::Filter::dwtForward(std::vector<double>& data, const std::string& wavelet_type, int family){
192  int origsize=data.size();
193  //make sure data size if power of 2
194  while(data.size()&(data.size()-1))
195  data.push_back(data.back());
196 
197  int nsize=data.size();
198  gsl_wavelet *w;
199  gsl_wavelet_workspace *work;
200  assert(nsize);
201  w=gsl_wavelet_alloc(getWaveletType(wavelet_type),family);
202  work=gsl_wavelet_workspace_alloc(nsize);
203  gsl_wavelet_transform_forward(w,&(data[0]),1,nsize,work);
204  data.erase(data.begin()+origsize,data.end());
205  gsl_wavelet_free (w);
206  gsl_wavelet_workspace_free (work);
207 }
208 
209 //todo: support different padding strategies
210 void filter::Filter::dwtInverse(std::vector<double>& data, const std::string& wavelet_type, int family){
211  int origsize=data.size();
212  //make sure data size if power of 2
213  while(data.size()&(data.size()-1))
214  data.push_back(data.back());
215  int nsize=data.size();
216  gsl_wavelet *w;
217  gsl_wavelet_workspace *work;
218  assert(nsize);
219  w=gsl_wavelet_alloc(getWaveletType(wavelet_type),family);
220  work=gsl_wavelet_workspace_alloc(nsize);
221  gsl_wavelet_transform_inverse(w,&(data[0]),1,nsize,work);
222  data.erase(data.begin()+origsize,data.end());
223  gsl_wavelet_free (w);
224  gsl_wavelet_workspace_free (work);
225 }
226 
227 //todo: support different padding strategies
228 void filter::Filter::dwtCut(std::vector<double>& data, const std::string& wavelet_type, int family, double cut){
229  int origsize=data.size();
230  //make sure data size if power of 2
231  while(data.size()&(data.size()-1))
232  data.push_back(data.back());
233  int nsize=data.size();
234  gsl_wavelet *w;
235  gsl_wavelet_workspace *work;
236  assert(nsize);
237  w=gsl_wavelet_alloc(getWaveletType(wavelet_type),family);
238  work=gsl_wavelet_workspace_alloc(nsize);
239  gsl_wavelet_transform_forward(w,&(data[0]),1,nsize,work);
240  std::vector<double> abscoeff(data.size());
241  size_t* p=new size_t[data.size()];
242  for(int index=0;index<data.size();++index){
243  abscoeff[index]=fabs(data[index]);
244  }
245  int nc=(100-cut)/100.0*nsize;
246  gsl_sort_index(p,&(abscoeff[0]),1,nsize);
247  for(int i=0;(i+nc)<nsize;i++)
248  data[p[i]]=0;
249  gsl_wavelet_transform_inverse(w,&(data[0]),1,nsize,work);
250  data.erase(data.begin()+origsize,data.end());
251  delete[] p;
252  gsl_wavelet_free (w);
253  gsl_wavelet_workspace_free (work);
254 }
255 
256 void filter::Filter::morphology(const ImgReaderGdal& input, ImgWriterGdal& output, const std::string& method, int dim, short verbose)
257 {
258  // bool bverbose=(verbose>1)? true:false;
259  Vector2d<double> lineInput(input.nrOfBand(),input.nrOfCol());
260  Vector2d<double> lineOutput(input.nrOfBand(),input.nrOfCol());
261  const char* pszMessage;
262  void* pProgressArg=NULL;
263  GDALProgressFunc pfnProgress=GDALTermProgress;
264  double progress=0;
265  pfnProgress(progress,pszMessage,pProgressArg);
266  for(int y=0;y<input.nrOfRow();++y){
267  for(int iband=0;iband<input.nrOfBand();++iband)
268  input.readData(lineInput[iband],GDT_Float64,y,iband);
269  vector<double> pixelInput(input.nrOfBand());
270  vector<double> pixelOutput(input.nrOfBand());
271  for(int x=0;x<input.nrOfCol();++x){
272  pixelInput=lineInput.selectCol(x);
273  filter(pixelInput,pixelOutput,method,dim);
274  // morphology(pixelInput,pixelOutput,method,dim,bverbose);
275  for(int iband=0;iband<input.nrOfBand();++iband)
276  lineOutput[iband][x]=pixelOutput[iband];
277  }
278  for(int iband=0;iband<input.nrOfBand();++iband){
279  try{
280  output.writeData(lineOutput[iband],GDT_Float64,y,iband);
281  }
282  catch(string errorstring){
283  cerr << errorstring << "in band " << iband << ", line " << y << endl;
284  }
285  }
286  progress=(1.0+y)/output.nrOfRow();
287  pfnProgress(progress,pszMessage,pProgressArg);
288  }
289 }
290 
291 void filter::Filter::smoothNoData(const ImgReaderGdal& input, const std::string& interpolationType, ImgWriterGdal& output)
292 {
293  Vector2d<double> lineInput(input.nrOfBand(),input.nrOfCol());
294  Vector2d<double> lineOutput(input.nrOfBand(),input.nrOfCol());
295  const char* pszMessage;
296  void* pProgressArg=NULL;
297  GDALProgressFunc pfnProgress=GDALTermProgress;
298  double progress=0;
299  pfnProgress(progress,pszMessage,pProgressArg);
300  for(int y=0;y<input.nrOfRow();++y){
301  for(int iband=0;iband<input.nrOfBand();++iband)
302  input.readData(lineInput[iband],GDT_Float64,y,iband);
303  vector<double> pixelInput(input.nrOfBand());
304  vector<double> pixelOutput(input.nrOfBand());
305  for(int x=0;x<input.nrOfCol();++x){
306  pixelInput=lineInput.selectCol(x);
307  smoothNoData(pixelInput,interpolationType,pixelOutput);
308  for(int iband=0;iband<input.nrOfBand();++iband)
309  lineOutput[iband][x]=pixelOutput[iband];
310  }
311  for(int iband=0;iband<input.nrOfBand();++iband){
312  try{
313  output.writeData(lineOutput[iband],GDT_Float64,y,iband);
314  }
315  catch(string errorstring){
316  cerr << errorstring << "in band " << iband << ", line " << y << endl;
317  }
318  }
319  progress=(1.0+y)/output.nrOfRow();
320  pfnProgress(progress,pszMessage,pProgressArg);
321  }
322 }
323 
324 void filter::Filter::smooth(const ImgReaderGdal& input, ImgWriterGdal& output, short dim)
325 {
326  assert(dim>0);
327  m_taps.resize(dim);
328  for(int itap=0;itap<dim;++itap)
329  m_taps[itap]=1.0/dim;
330  filter(input,output);
331 }
332 
333 void filter::Filter::filter(const ImgReaderGdal& input, ImgWriterGdal& output)
334 {
335  Vector2d<double> lineInput(input.nrOfBand(),input.nrOfCol());
336  Vector2d<double> lineOutput(input.nrOfBand(),input.nrOfCol());
337  const char* pszMessage;
338  void* pProgressArg=NULL;
339  GDALProgressFunc pfnProgress=GDALTermProgress;
340  double progress=0;
341  pfnProgress(progress,pszMessage,pProgressArg);
342  for(int y=0;y<input.nrOfRow();++y){
343  for(int iband=0;iband<input.nrOfBand();++iband)
344  input.readData(lineInput[iband],GDT_Float64,y,iband);
345  vector<double> pixelInput(input.nrOfBand());
346  vector<double> pixelOutput(input.nrOfBand());
347  for(int x=0;x<input.nrOfCol();++x){
348  pixelInput=lineInput.selectCol(x);
349  filter(pixelInput,pixelOutput);
350  for(int iband=0;iband<input.nrOfBand();++iband)
351  lineOutput[iband][x]=pixelOutput[iband];
352  }
353  for(int iband=0;iband<input.nrOfBand();++iband){
354  try{
355  output.writeData(lineOutput[iband],GDT_Float64,y,iband);
356  }
357  catch(string errorstring){
358  cerr << errorstring << "in band " << iband << ", line " << y << endl;
359  }
360  }
361  progress=(1.0+y)/output.nrOfRow();
362  pfnProgress(progress,pszMessage,pProgressArg);
363  }
364 }
365 
366 void filter::Filter::stat(const ImgReaderGdal& input, ImgWriterGdal& output, const std::string& method)
367 {
368  Vector2d<double> lineInput(input.nrOfBand(),input.nrOfCol());
369  assert(output.nrOfCol()==input.nrOfCol());
370  vector<double> lineOutput(output.nrOfCol());
372  stat.setNoDataValues(m_noDataValues);
373  const char* pszMessage;
374  void* pProgressArg=NULL;
375  GDALProgressFunc pfnProgress=GDALTermProgress;
376  double progress=0;
377  pfnProgress(progress,pszMessage,pProgressArg);
378  for(int y=0;y<input.nrOfRow();++y){
379  for(int iband=0;iband<input.nrOfBand();++iband)
380  input.readData(lineInput[iband],GDT_Float64,y,iband);
381  vector<double> pixelInput(input.nrOfBand());
382  for(int x=0;x<input.nrOfCol();++x){
383  pixelInput=lineInput.selectCol(x);
384  switch(getFilterType(method)){
385  case(filter::median):
386  lineOutput[x]=stat.median(pixelInput);
387  break;
388  case(filter::min):
389  lineOutput[x]=stat.mymin(pixelInput);
390  break;
391  case(filter::max):
392  lineOutput[x]=stat.mymax(pixelInput);
393  break;
394  case(filter::sum):
395  lineOutput[x]=stat.sum(pixelInput);
396  break;
397  case(filter::var):
398  lineOutput[x]=stat.var(pixelInput);
399  break;
400  case(filter::stdev):
401  lineOutput[x]=sqrt(stat.var(pixelInput));
402  break;
403  case(filter::mean):
404  lineOutput[x]=stat.mean(pixelInput);
405  break;
406  case(filter::percentile):
407  assert(m_threshold.size());
408  lineOutput[x]=stat.percentile(pixelInput,pixelInput.begin(),pixelInput.end(),m_threshold[0]);
409  break;
410  default:
411  std::string errorString="method not supported";
412  throw(errorString);
413  break;
414  }
415  }
416  try{
417  output.writeData(lineOutput,GDT_Float64,y);
418  }
419  catch(string errorstring){
420  cerr << errorstring << "in line " << y << endl;
421  }
422  progress=(1.0+y)/output.nrOfRow();
423  pfnProgress(progress,pszMessage,pProgressArg);
424  }
425 }
426 
427 void filter::Filter::filter(const ImgReaderGdal& input, ImgWriterGdal& output, const std::string& method, int dim)
428 {
429  Vector2d<double> lineInput(input.nrOfBand(),input.nrOfCol());
430  Vector2d<double> lineOutput(input.nrOfBand(),input.nrOfCol());;
431  const char* pszMessage;
432  void* pProgressArg=NULL;
433  GDALProgressFunc pfnProgress=GDALTermProgress;
434  double progress=0;
435  pfnProgress(progress,pszMessage,pProgressArg);
436  for(int y=0;y<input.nrOfRow();++y){
437  for(int iband=0;iband<input.nrOfBand();++iband)
438  input.readData(lineInput[iband],GDT_Float64,y,iband);
439  vector<double> pixelInput(input.nrOfBand());
440  vector<double> pixelOutput;
441  for(int x=0;x<input.nrOfCol();++x){
442  pixelInput=lineInput.selectCol(x);
443  filter(pixelInput,pixelOutput,method,dim);
444  for(int iband=0;iband<pixelOutput.size();++iband){
445  lineOutput[iband][x]=pixelOutput[iband];
446  // if(pixelInput[iband]!=0)
447  // assert(pixelOutput[iband]!=0);
448  }
449  }
450  for(int iband=0;iband<input.nrOfBand();++iband){
451  try{
452  output.writeData(lineOutput[iband],GDT_Float64,y,iband);
453  }
454  catch(string errorstring){
455  cerr << errorstring << "in band " << iband << ", line " << y << endl;
456  }
457  }
458  progress=(1.0+y)/output.nrOfRow();
459  pfnProgress(progress,pszMessage,pProgressArg);
460  }
461 }
462 
463 void filter::Filter::getSavGolayCoefficients(vector<double> &tapz, int np, int nl, int nr, int ld, int m) {
464  int j, k, imj, ipj, kk, mm;
465  double d, fac, sum;
466 
467  // c.resize(nl+1+nr);
468  vector<double> tmpc(np);
469  if(np < nl + nr + 1 || nl < 0 || nr < 0 || ld > m || nl + nr < m) {
470  cerr << "bad args in savgol" << endl;
471  return;
472  }
473  vector<int> indx(m + 1, 0);
474  vector<double> a((m + 1) * (m + 1), 0.0);
475  vector<double> b(m + 1, 0.0);
476 
477  for(ipj = 0; ipj <= (m << 1); ++ipj) {
478  sum = (ipj ? 0.0 : 1.0);
479  for(k = 1; k <= nr; ++k)
480  sum += (int)pow((double)k, (double)ipj);
481  for(k = 1; k <= nl; ++k)
482  sum += (int)pow((double) - k, (double)ipj);
483  mm = (ipj < 2 * m - ipj ? ipj : 2 * m - ipj);
484  for(imj = -mm; imj <= mm; imj += 2)
485  a[(ipj + imj) / 2 * (m + 1) + (ipj - imj) / 2] = sum;
486  }
487  ludcmp(a, indx, d);
488 
489  for(j = 0; j < m + 1; ++j)
490  b[j] = 0.0;
491  b[ld] = 1.0;
492 
493  lubksb(a, indx, b);
494  // for(kk = 0; kk < np; ++kk)
495  // c[kk] = 0.0;
496  for(k = -nl; k <= nr; ++k) {
497  // for(k = -nl; k < nr; ++k) {
498  sum = b[0];
499  fac = 1.0;
500  for(mm = 1; mm <= m; ++mm)
501  sum += b[mm] * (fac *= k);
502  // store in wrap=around order
503  kk = (np - k) % np;
504  //re-order c as I need for taps
505  // kk=k+nl;
506  tmpc[kk] = sum;
507  }
508  tapz.resize(nl+1+nr);
509  // for(k=0;k<nl+1+nr)
510  tapz[tapz.size()/2]=tmpc[0];
511  //past data points
512  for(k=1;k<=tapz.size()/2;++k)
513  tapz[tapz.size()/2-k]=tmpc[k];
514  //future data points
515  for(k=1;k<=tapz.size()/2;++k)
516  tapz[tapz.size()/2+k]=tmpc[np-k];
517 }
518 
519 void filter::Filter::ludcmp(vector<double> &a, vector<int> &indx, double &d) {
520  const double TINY = 1.0e-20;
521  int i, imax = -1, j, k;
522  double big, dum, sum, temp;
523 
524  int n = indx.size();
525  vector<double> vv(n, 0.0);
526 
527  d = 1.0;
528  for(i = 0; i < n; ++i) {
529  big = 0.0;
530  for(j = 0; j < n; ++j)
531  if((temp = fabs(a[i * n + j])) > big) big = temp;
532 
533  if(big == 0.0) {
534  cerr << "Singular matrix in routine ludcmp" << endl;
535  return;
536  }
537  vv[i] = 1. / big;
538  }
539 
540  for(j = 0; j < n; ++j) {
541  for(i = 0; i < j; ++i) {
542  sum = a[i * n + j];
543  for(k = 0; k < i; ++k)
544  sum -= a[i * n + k] * a[k * n + j];
545  a[i * n + j] = sum;
546  }
547  big = 0.0;
548  for(i = j; i < n; ++i) {
549  sum = a[i * n + j];
550  for(k = 0; k < j; ++k)
551  sum -= a[i * n + k] * a[k * n + j];
552  a[i * n + j] = sum;
553  if((dum = vv[i] * fabs(sum)) >= big) {
554  big = dum;
555  imax = i;
556  }
557  }
558 
559  if(j != imax) {
560  for(k = 0; k < n; ++k) {
561  dum = a[imax * n + k];
562  a[imax * n + k] = a[j * n + k];
563  a[j * n + k] = dum;
564  }
565  d = -d;
566  vv[imax] = vv[j];
567  }
568  indx[j] = imax;
569  if(a[j * n + j] == 0.0) a[j * n + j] = TINY;
570  if(j != n - 1) {
571  dum = 1. / a[j * n + j];
572  for(i = j + 1; i < n; ++i)
573  a[i * n + j] *= dum;
574  }
575  }
576 }
577 
578 void filter::Filter::lubksb(vector<double> &a, vector<int> &indx, vector<double> &b) {
579  int i, ii = 0, ip, j;
580  double sum;
581  int n = indx.size();
582 
583  for(i = 0; i < n; ++i) {
584  ip = indx[i];
585  sum = b[ip];
586  b[ip] = b[i];
587  if(ii != 0)
588  for(j = ii - 1; j < i; ++j)
589  sum -= a[i * n + j] * b[j];
590  else if(sum != 0.0)
591  ii = i + 1;
592  b[i] = sum;
593  }
594  for(i = n - 1; i >= 0; --i) {
595  sum = b[i];
596  for(j = i + 1; j < n; ++j)
597  sum -= a[i * n + j] * b[j];
598  b[i] = sum / a[i * n + i];
599  }
600 }
601 
602 double filter::Filter::getCentreWavelength(const std::vector<double> &wavelengthIn, const Vector2d<double>& srf, const std::string& interpolationType, double delta, bool verbose)
603 {
604  assert(srf.size()==2);//[0]: wavelength, [1]: response function
605  int nband=srf[0].size();
606  double start=floor(wavelengthIn[0]);
607  double end=ceil(wavelengthIn.back());
608  if(verbose)
609  std::cout << "wavelengths in [" << start << "," << end << "]" << std::endl << std::flush;
610 
612 
613  gsl_interp_accel *acc;
614  stat.allocAcc(acc);
615  gsl_spline *spline;
616  stat.getSpline(interpolationType,nband,spline);
617  stat.initSpline(spline,&(srf[0][0]),&(srf[1][0]),nband);
618  if(verbose)
619  std::cout << "calculating norm of srf" << std::endl << std::flush;
620  double norm=0;
621  norm=gsl_spline_eval_integ(spline,srf[0].front(),srf[0].back(),acc);
622  if(verbose)
623  std::cout << "norm of srf: " << norm << std::endl << std::flush;
624  gsl_spline_free(spline);
625  gsl_interp_accel_free(acc);
626  std::vector<double> wavelength_fine;
627  for(double win=floor(wavelengthIn[0]);win<=ceil(wavelengthIn.back());win+=delta)
628  wavelength_fine.push_back(win);
629 
630  if(verbose)
631  std::cout << "interpolate wavelengths to " << wavelength_fine.size() << " entries " << std::endl;
632  std::vector<double> srf_fine;//spectral response function, interpolated for wavelength_fine
633 
634  stat.interpolateUp(srf[0],srf[1],wavelength_fine,interpolationType,srf_fine,verbose);
635  assert(srf_fine.size()==wavelength_fine.size());
636 
637  gsl_interp_accel *accOut;
638  stat.allocAcc(accOut);
639  gsl_spline *splineOut;
640  stat.getSpline(interpolationType,wavelength_fine.size(),splineOut);
641  assert(splineOut);
642 
643  std::vector<double> wavelengthOut(wavelength_fine.size());
644 
645  for(int iband=0;iband<wavelengthOut.size();++iband)
646  wavelengthOut[iband]=wavelength_fine[iband]*srf_fine[iband];
647 
648  stat.initSpline(splineOut,&(wavelength_fine[0]),&(wavelengthOut[0]),wavelength_fine.size());
649  double centreWavelength=gsl_spline_eval_integ(splineOut,start,end,accOut)/norm;
650 
651  gsl_spline_free(splineOut);
652  gsl_interp_accel_free(accOut);
653 
654  return(centreWavelength);
655 }
656 
657 // void filter::Filter::applyFwhm(const vector<double> &wavelengthIn, const ImgReaderGdal& input, const vector<double> &wavelengthOut, const vector<double> &fwhm, const std::string& interpolationType, ImgWriterGdal& output, bool verbose){
658 // Vector2d<double> lineInput(input.nrOfBand(),input.nrOfCol());
659 // Vector2d<double> lineOutput(wavelengthOut.size(),input.nrOfCol());
660 // const char* pszMessage;
661 // void* pProgressArg=NULL;
662 // GDALProgressFunc pfnProgress=GDALTermProgress;
663 // double progress=0;
664 // pfnProgress(progress,pszMessage,pProgressArg);
665 // for(int y=0;y<input.nrOfRow();++y){
666 // for(int iband=0;iband<input.nrOfBand();++iband)
667 // input.readData(lineInput[iband],GDT_Float64,y,iband);
668 // applyFwhm<double>(wavelengthIn,lineInput,wavelengthOut,fwhm, interpolationType, lineOutput, verbose);
669 // for(int iband=0;iband<output.nrOfBand();++iband){
670 // try{
671 // output.writeData(lineOutput[iband],GDT_Float64,y,iband);
672 // }
673 // catch(string errorstring){
674 // cerr << errorstring << "in band " << iband << ", line " << y << endl;
675 // }
676 // }
677 // progress=(1.0+y)/output.nrOfRow();
678 // pfnProgress(progress,pszMessage,pProgressArg);
679 // }
680 // }
681 
682 // void filter::Filter::applySrf(const vector<double> &wavelengthIn, const ImgReaderGdal& input, const vector< Vector2d<double> > &srf, const std::string& interpolationType, ImgWriterGdal& output, bool verbose){
683 // assert(output.nrOfBand()==srf.size());
684 // double centreWavelength=0;
685 // Vector2d<double> lineInput(input.nrOfBand(),input.nrOfCol());
686 // const char* pszMessage;
687 // void* pProgressArg=NULL;
688 // GDALProgressFunc pfnProgress=GDALTermProgress;
689 // double progress=0;
690 // pfnProgress(progress,pszMessage,pProgressArg);
691 // for(int y=0;y<input.nrOfRow();++y){
692 // for(int iband=0;iband<input.nrOfBand();++iband)
693 // input.readData(lineInput[iband],GDT_Float64,y,iband);
694 // for(int isrf=0;isrf<srf.size();++isrf){
695 // vector<double> lineOutput(input.nrOfCol());
696 // centreWavelength=applySrf<double>(wavelengthIn,lineInput,srf[isrf], interpolationType, lineOutput, verbose);
697 // for(int iband=0;iband<output.nrOfBand();++iband){
698 // try{
699 // output.writeData(lineOutput,GDT_Float64,y,isrf);
700 // }
701 // catch(string errorstring){
702 // cerr << errorstring << "in band " << iband << ", line " << y << endl;
703 // }
704 // }
705 // }
706 // progress=(1.0+y)/output.nrOfRow();
707 // pfnProgress(progress,pszMessage,pProgressArg);
708 // }
709 // }