pktools  2.6.3
Processing Kernel for geospatial data
pkfilterascii.cc
1 /**********************************************************************
2 pkfilterascii.cc: program to filter data in an ASCII file
3 Copyright (C) 2008-2014 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 <assert.h>
21 #include <iostream>
22 #include <string>
23 #include <fstream>
24 #include <math.h>
25 #include <sys/types.h>
26 #include <stdio.h>
27 #include "base/Optionpk.h"
28 #include "base/Vector2d.h"
29 #include "algorithms/Filter.h"
30 #include "fileclasses/FileReaderAscii.h"
31 
32 extern "C" {
33 #include <gsl/gsl_sort.h>
34 }
35 
36 using namespace std;
37 
38 /*------------------
39  Main procedure
40  ----------------*/
41 int main(int argc,char **argv) {
42  Optionpk<std::string> input_opt("i","input","input ASCII file");
43  Optionpk<std::string> output_opt("o", "output", "Output ASCII file");
44  Optionpk<int> inputCols_opt("ic", "inputCols", "input columns (e.g., for three dimensional input data in first three columns use: -ic 0 -ic 1 -ic 2");
45  Optionpk<std::string> method_opt("f", "filter", "filter function (to be implemented: dwt, dwti,dwt_cut)");
46  Optionpk<std::string> wavelet_type_opt("wt", "wavelet", "wavelet type: daubechies,daubechies_centered, haar, haar_centered, bspline, bspline_centered", "daubechies");
47  Optionpk<int> family_opt("wf", "family", "wavelet family (vanishing moment, see also http://www.gnu.org/software/gsl/manual/html_node/DWT-Initialization.html)", 4);
48  Optionpk<double> threshold_opt("cut", "cut", "threshold to cut dwt coefficients. Use 0 to keep all.", 0);
49  Optionpk<int> dimZ_opt("dz", "dz", "filter kernel size in z (band or spectral dimension), must be odd (example: 3).. Set dz>0 if 1-D filter must be used in band domain");
50  Optionpk<double> tapZ_opt("tapz", "tapz", "taps used for spectral filtering");
51  Optionpk<double> fwhm_opt("fwhm", "fwhm", "list of full width half to apply spectral filtering (-fwhm band1 -fwhm band2 ...)");
52  Optionpk<std::string> srf_opt("srf", "srf", "list of ASCII files containing spectral response functions (two columns: wavelength response)");
53  Optionpk<int> wavelengthIn_opt("win", "wavelengthIn", "column number of input ASCII file containing wavelengths");
54  Optionpk<double> wavelengthOut_opt("wout", "wavelengthOut", "list of wavelengths in output spectrum (-wout band1 -wout band2 ...)");
55  Optionpk<std::string> interpolationType_opt("interp", "interp", "type of interpolation for spectral filtering (see http://www.gnu.org/software/gsl/manual/html_node/Interpolation-Types.html)","akima");
56  Optionpk<bool> transpose_opt("t", "transpose", "transpose output with samples in rows and wavelengths in cols", false);
57  Optionpk<short> verbose_opt("v", "verbose", "verbose mode if > 0", 0,2);
58 
59  tapZ_opt.setHide(1);
60  fwhm_opt.setHide(1);
61  srf_opt.setHide(1);
62  wavelengthIn_opt.setHide(1);
63  wavelengthOut_opt.setHide(1);
64  interpolationType_opt.setHide(1);
65  transpose_opt.setHide(1);
66  wavelet_type_opt.setHide(1);
67  family_opt.setHide(1);
68  threshold_opt.setHide(1);
69 
70  bool doProcess;//stop process when program was invoked with help option (-h --help)
71  try{
72  doProcess=input_opt.retrieveOption(argc,argv);
73  output_opt.retrieveOption(argc,argv);
74  inputCols_opt.retrieveOption(argc,argv);
75  method_opt.retrieveOption(argc,argv);
76  dimZ_opt.retrieveOption(argc,argv);
77  tapZ_opt.retrieveOption(argc,argv);
78  fwhm_opt.retrieveOption(argc,argv);
79  srf_opt.retrieveOption(argc,argv);
80  wavelengthIn_opt.retrieveOption(argc,argv);
81  wavelengthOut_opt.retrieveOption(argc,argv);
82  interpolationType_opt.retrieveOption(argc,argv);
83  transpose_opt.retrieveOption(argc,argv);
84  wavelet_type_opt.retrieveOption(argc,argv);
85  family_opt.retrieveOption(argc,argv);
86  threshold_opt.retrieveOption(argc,argv);
87  verbose_opt.retrieveOption(argc,argv);
88  }
89  catch(string predefinedString){
90  std::cout << predefinedString << std::endl;
91  exit(0);
92  }
93  if(!doProcess){
94  cout << endl;
95  cout << "Usage: pkfilterascii -i input.txt [-ic column]*" << endl;
96  cout << endl;
97  std::cout << "short option -h shows basic options only, use long option --help to show all options" << std::endl;
98  exit(0);//help was invoked, stop processing
99  }
100 
101  Vector2d<double> inputData(inputCols_opt.size());
102  Vector2d<double> filteredData(inputCols_opt.size());
103  std::vector<double> wavelengthIn;
104  std::vector<double> wavelengthOut;
105  assert(input_opt.size());
106  FileReaderAscii asciiReader(input_opt[0]);
107  if(wavelengthIn_opt.size())
108  asciiReader.readData(wavelengthIn,wavelengthIn_opt[0]);
109  assert(inputCols_opt.size());
110  asciiReader.readData(inputData,inputCols_opt);
111  if(verbose_opt[0]){
112  std::cout << "wavelengthIn.size(): " << wavelengthIn.size() << std::endl;
113  std::cout << "inputData[0].size(): " << inputData[0].size() << std::endl;
114  }
115  if(wavelengthIn.size())
116  assert(wavelengthIn.size()==inputData[0].size());
117  asciiReader.close();
118  filter::Filter filter1d;
119  if(fwhm_opt.size()){
120  filteredData.resize(inputCols_opt.size(),wavelengthOut_opt.size());
121  assert(wavelengthIn_opt.size());
122  if(verbose_opt[0])
123  std::cout << "spectral filtering to " << fwhm_opt.size() << " bands with provided fwhm " << std::endl;
124  assert(wavelengthOut_opt.size()==fwhm_opt.size());
125  std::vector<double> fwhmData(wavelengthOut_opt.size());
126  for(int icol=0;icol<inputCols_opt.size();++icol)
127  filter1d.applyFwhm<double>(wavelengthIn,inputData[icol], wavelengthOut_opt,fwhm_opt, interpolationType_opt[0], filteredData[icol],verbose_opt[0]);
128  if(verbose_opt[0])
129  std::cout << "spectra filtered to " << wavelengthOut_opt.size() << " bands" << std::endl;
130  wavelengthOut=wavelengthOut_opt;
131  }
132  else if(srf_opt.size()){
133  wavelengthOut.resize(srf_opt.size());
134  filteredData.resize(inputCols_opt.size(),srf_opt.size());
135  Vector2d<double> srfData(srf_opt.size(),inputCols_opt.size());//transposed output
136  if(verbose_opt[0])
137  std::cout << "spectral filtering to " << srf_opt.size() << " bands with provided SRF " << std::endl;
138  std::vector< Vector2d<double> > srf(srf_opt.size());//[0] srf_nr, [1]: wavelength, [2]: response
139  ifstream srfFile;
140  for(int isrf=0;isrf<srf_opt.size();++isrf){
141  srf[isrf].resize(2);
142  srfFile.open(srf_opt[isrf].c_str());
143  double v;
144  //add 0 to make sure srf is 0 at boundaries after interpolation step
145  srf[isrf][0].push_back(0);
146  srf[isrf][1].push_back(0);
147  srf[isrf][0].push_back(1);
148  srf[isrf][1].push_back(0);
149  while(srfFile >> v){
150  srf[isrf][0].push_back(v);
151  srfFile >> v;
152  srf[isrf][1].push_back(v);
153  }
154  srfFile.close();
155  //add 0 to make sure srf[isrf] is 0 at boundaries after interpolation step
156  srf[isrf][0].push_back(srf[isrf][0].back()+1);
157  srf[isrf][1].push_back(0);
158  srf[isrf][0].push_back(srf[isrf][0].back()+1);
159  srf[isrf][1].push_back(0);
160  if(verbose_opt[0])
161  cout << "srf file details: " << srf[isrf][0].size() << " wavelengths defined" << endl;
162  if(verbose_opt[0]>1){
163  for(int iw=0;iw<srf[isrf][0].size();++iw)
164  std::cout << srf[isrf][0][iw] << " " << srf[isrf][1][iw] << std::endl;
165  }
166  }
167  double centreWavelength=0;
168  for(int icol=0;icol<inputCols_opt.size();++icol)
169  filteredData[icol].resize(srf.size());
170 
171  for(int isrf=0;isrf<srf.size();++isrf){
172  double delta=1.0;
173  bool normalize=true;
174  centreWavelength=filter1d.applySrf<double>(wavelengthIn,inputData,srf[isrf], interpolationType_opt[0], srfData[isrf], delta, normalize,1,true, verbose_opt[0]);
175  if(verbose_opt[0])
176  std::cout << "centre wavelength srf " << isrf << ": " << centreWavelength << std::endl;
177  wavelengthOut[isrf]=static_cast<int>(centreWavelength+0.5);
178  }
179  srfData.transpose(filteredData);
180  if(verbose_opt[0])
181  std::cout << "spectra filtered to " << srf.size() << " bands" << std::endl;
182  }
183  else{//no filtering
184  if(verbose_opt[0])
185  std::cout << "no filtering selected" << std::endl;
186  for(int icol=0;icol<inputCols_opt.size();++icol)
187  filteredData[icol]=inputData[icol];
188  }
189 
190  if(method_opt.size()){
191  wavelengthOut=wavelengthIn;
192  for(int icol=0;icol<inputCols_opt.size();++icol){
193  switch(filter::Filter::getFilterType(method_opt[0])){
194  case(filter::dwt):
195  filter1d.dwtForward(filteredData[icol],wavelet_type_opt[0],family_opt[0]);
196  break;
197  case(filter::dwti):
198  filter1d.dwtInverse(filteredData[icol],wavelet_type_opt[0],family_opt[0]);
199  break;
200  case(filter::dwt_cut):
201  filter1d.dwtCut(filteredData[icol],wavelet_type_opt[0],family_opt[0],threshold_opt[0]);
202  break;
203  case(filter::smooth):
204  if(tapZ_opt.size()){
205  filter1d.setTaps(tapZ_opt);
206  filter1d.filter(inputData[icol],filteredData[icol]);
207  }
208  else{
209  assert(dimZ_opt.size());
210  filter1d.smooth(inputData[icol],filteredData[icol],dimZ_opt[0]);
211  }
212  break;
213  default:
214  assert(tapZ_opt.size());
215  filter1d.filter(inputData[icol],filteredData[icol]);
216  // if(verbose_opt[0])
217  // std::cout << "method to be implemented" << std::endl;
218  // exit(1);
219  break;
220  }
221  }
222  }
223  ofstream outputStream;
224  if(!output_opt.empty())
225  outputStream.open(output_opt[0].c_str(),ios::out);
226 
227  if(verbose_opt[0])
228  std::cout << "stream to output" << std::endl;
229  if(transpose_opt[0]){
230  for(int icol=0;icol<inputCols_opt.size();++icol){
231  for(int iband=0;iband<filteredData[icol].size();++iband){
232  if(!output_opt.empty()){
233  outputStream << filteredData[icol][iband];
234  if(iband<filteredData[icol].size()-1)
235  outputStream << " ";
236  else
237  outputStream << std::endl;
238  }
239  else{
240  std::cout << filteredData[icol][iband];
241  if(iband<filteredData[icol].size()-1)
242  std::cout << " ";
243  else
244  std::cout << std::endl;
245  }
246  }
247  }
248  }
249  else{
250  // int nband=wavelengthOut.size()? wavelengthOut.size() : filteredData[0].size();
251  int nband=0;
252  if(method_opt.size()){
253  switch(filter::Filter::getFilterType(method_opt[0])){
254  case(filter::dwt):
255  nband=filteredData[0].size();
256  break;
257  case(filter::dwti):
258  nband=filteredData[0].size();
259  break;
260  case(filter::dwt_cut):
261  nband=filteredData[0].size();
262  break;
263  default:
264  nband=wavelengthOut.size();
265  break;
266  }
267  }
268  else
269  nband=wavelengthOut.size();
270  if(verbose_opt[0]){
271  std::cout << "number of bands: " << nband << std::endl;
272  std::cout << "wavelengthOut.size(): " << wavelengthOut.size() << std::endl;
273  }
274  for(int iband=0;iband<nband;++iband){
275  if(!output_opt.empty()){
276  if(wavelengthOut.size())
277  outputStream << wavelengthOut[iband] << " ";
278  else if(wavelengthIn_opt.size())
279  outputStream << iband << " ";
280  }
281  else{
282  if(wavelengthOut.size())
283  std::cout << wavelengthOut[iband] << " ";
284  else if(wavelengthIn_opt.size())
285  std::cout << iband << " ";
286  }
287  for(int icol=0;icol<inputCols_opt.size();++icol){
288  if(!output_opt.empty()){
289  outputStream << filteredData[icol][iband];
290  if(icol<inputCols_opt.size()-1)
291  outputStream << " ";
292  else
293  outputStream << std::endl;
294  }
295  else{
296  std::cout << filteredData[icol][iband];
297  if(icol<inputCols_opt.size()-1)
298  std::cout << " ";
299  else
300  std::cout << std::endl;
301  }
302  }
303  }
304  }
305  if(!output_opt.empty())
306  outputStream.close();
307  return 0;
308 }