96 "usage: deconv [-v] [-o] [-damping=v] [-cosine=v]" "\n" 97 " [-transform=file] [-type f]" "\n" 98 " [-datetolerance f\n" 99 " [-demean[=n]] [-dtrend[=n]]" "\n" 100 " response input [t:l] [input [t:l]]" "\n" 101 " or: deconv --help|-h" "\n" 107 "response impulse response of filter" "\n" 108 "input input time series" "\n" 109 " Several filenames together with trace selectors can be" "\n" 110 " used. The first to traces read will be used for the" "\n" 112 " trace #1: input to filter" "\n" 113 " trace #2: output from filter" "\n" 115 "-verbose be verbose" "\n" 116 "-overwrite overwrite existing output file" "\n" 117 "-damping v set damping to fraction v of average input energy" "\n" 118 "-cosine v use cosine taper, wherer 0<v<0.5 is the taper fraction" "\n" 120 " set a tolerance level f for comparison of date of\n" 121 " input time series; dates will be considered as different\n" 122 " if they differ by more than a fraction f of the average\n" 123 " sampling interval\n" 124 "-transform f write Fourier transform of impulse response to file \"f\"" "\n" 125 " 1st column: frequency\n" 126 " 2nd column: amplitude response\n" 127 " 3nd column: phase response\n" 128 " 4th column: amplitude response from Fourier amplitudes\n" 129 " without damping (ragularization)\n" 130 " 5th column: FFT of filter input signal\n" 131 " 6th column: FFT of filter output signal\n" 132 "-type f data input files have format \"f\"" "\n" 133 "-demean[=n] remove average (determined from n samples)" "\n" 134 "-detrend[=n] remove trend (determined from n samples)" "\n" 136 "The program reads the input and output signals for a linear time" "\n" 137 "invariant filter from the SFF data files \"input\" and \"output\"." "\n" 138 "From these the impulse response function of the filter is" "\n" 139 "calulated by a stabilized deconvolution in the Fourier domain." "\n" 140 "The result will written to the SFF data file \"response\", where" "\n" 141 "the source time defines the origin." "\n" 143 "The default taper is a cosine taper of 0.5 (i.e. Hanning)." "\n" 144 "Setting the cosine taper fraction to 0. will result in a" "\n" 149 using namespace tfxx::cmdline;
150 static Declare options[]=
155 {
"verbose",arg_no,
"-"},
157 {
"overwrite",arg_no,
"-"},
159 {
"demean",arg_opt,
"0"},
161 {
"cosine",arg_yes,
"0.5"},
163 {
"transform",arg_yes,
"coeff.tab"},
165 {
"damping",arg_yes,
"0.1"},
167 {
"type",arg_yes,
"sff"},
169 {
"detrend",arg_opt,
"0"},
171 {
"datetolerance",arg_yes,
"0."},
178 cerr << usage_text << endl;
183 Commandline cmdline(iargc, argv, options);
186 if (cmdline.optset(0))
188 cerr << usage_text << endl;
189 cerr << help_text << endl;
199 opt.
demean=cmdline.optset(3);
200 opt.
ndemean=cmdline.int_arg(3);
204 opt.
damping=cmdline.double_arg(6);
212 "Damping fraction is out of meaningful range");
222 TFXX_assert(cmdline.extra(),
"missing output file name");
223 std::string impulseresponsefilename=cmdline.next();
225 TFXX_assert(cmdline.extra(),
"missing input file name");
227 tfxx::cmdline::Tparsed
228 filenames=tfxx::cmdline::parse_cmdline(cmdline,
keys);
231 std::string filterinputname, filteroutputname;
232 int filterinputtrace, filteroutputtrace;
234 tfxx::cmdline::Tparsed::const_iterator I=filenames.begin();
235 TFXX_assert(I!=filenames.end(),
"Missing filter input file name");
236 std::string tracelist=
"1";
238 tfxx::RangeListStepper<int> rls(tfxx::string::rangelist<int>(tracelist));
239 TFXX_assert(rls.valid(),
"Illegal tracelist");
240 filterinputname=I->name;
241 filterinputtrace=rls.current();
246 TFXX_assert(I!=filenames.end(),
"Missing filter output file name");
249 rls=tfxx::RangeListStepper<int>(tfxx::string::rangelist<int>(tracelist));
250 TFXX_assert(rls.valid(),
"Illegal tracelist");
252 filteroutputname=I->name;
253 filteroutputtrace=rls.current();
256 cout <<
"filter input from file " << filterinputname
257 <<
" (trace #" << filterinputtrace <<
")" << endl;
258 cout <<
"filter output from file " << filteroutputname
259 <<
" (trace #" << filteroutputtrace <<
")" << endl;
264 sff::FREE processfree, tracefree;
265 std::ostringstream freeline;
272 sff::FREE finputfilefree, foutputfilefree;
277 if (opt.
verbose) { cout <<
"open input file " << filterinputname << endl; }
278 std::ifstream ifs(filterinputname.c_str());
280 is >> finputfilefree;
282 while (itrace!=filterinputtrace) { is.skipseries(); ++itrace; }
283 TFXX_assert(is.good(),
"Illegal trace for filter input");
286 tracefree.append(
"**** filter input signal");
287 processfree.append(
"filter input signal");
288 freeline << filterinputname <<
"(trace " << filterinputtrace <<
")";
289 tracefree.append(freeline.str());
290 processfree.append(freeline.str());
291 processfree.append(finputfilefree);
292 processfree.append(finputtseries.header.free());
296 if (opt.
verbose) { cout <<
"open input file " << filteroutputname << endl; }
297 std::ifstream ifs(filteroutputname.c_str());
299 is >> foutputfilefree;
301 while (itrace!=filteroutputtrace) { is.skipseries(); ++itrace; }
302 TFXX_assert(is.good(),
"Illegal trace for filter output");
303 is >> foutputtseries;
305 tracefree.append(
"**** filter output signal");
306 processfree.append(
"filter output signal");
308 freeline << filteroutputname <<
"(trace " << filteroutputtrace <<
")";
309 tracefree.append(freeline.str());
310 processfree.append(freeline.str());
311 processfree.append(foutputfilefree);
312 processfree.append(foutputtseries.header.free());
316 sff::WID2compare compare(sff::Fnsamples | sff::Fdt | sff::Fdate);
318 if (opt.
verbose) { cout <<
"checking consistency..." << endl; }
319 if (!compare (finputtseries.header.wid2(),foutputtseries.header.wid2()))
321 cerr <<
"ERROR: header signature mismatch:" << endl;
322 cerr <<
"filter input:" << endl;
323 cerr << finputtseries.header.wid2().line();
324 cerr <<
"filter output:" << endl;
325 cerr << foutputtseries.header.wid2().line();
326 TFXX_abort(
"baling out...");
331 processfree.append(
"==== start processing ====");
336 freeline <<
"cosine taper fraction: " << opt.
cosinefrac;
337 processfree.append(freeline.str());
338 if (opt.
verbose) { cout << freeline.str() << endl; }
340 const sff::WID2& iwid2=finputtseries.header.wid2();
341 const sff::WID2& owid2=foutputtseries.header.wid2();
346 freeline <<
"remove average estimated for ";
347 if (opt.
ndemean==0) { freeline <<
"all"; }
else { freeline << opt.
ndemean; }
348 freeline <<
" samples";
349 if (opt.
verbose) { cout << freeline.str() << endl; }
350 processfree.append(freeline.str());
351 ts::filter::RemoveAverage demean(opt.
ndemean);
359 freeline <<
"remove trend estimated for ";
360 if (opt.
ndetrend==0) { freeline <<
"all"; }
362 freeline <<
" samples";
363 if (opt.
verbose) { cout << freeline.str() << endl; }
364 processfree.append(freeline.str());
365 ts::filter::RemoveTrend detrend(opt.
ndetrend);
371 taper.apply(finputtseries);
372 taper.apply(foutputtseries);
378 if (opt.
verbose) { cout <<
"Fourier transformation..." << endl; }
379 Tfft::Tspectrum icoeff=fft(finputtseries, iwid2.dt);
380 Tfft::Tspectrum ocoeff=fft(foutputtseries, owid2.dt);
383 if (opt.
verbose) { cout <<
"calculate energy in input signal..." << endl; }
386 aff::Browser<Tfft::Tspectrum> IC(icoeff);
389 energy += IC->real()*IC->real()+IC->imag()*IC->imag();
393 energy /= iwid2.nsamples;
394 double damping=energy*opt.
damping;
398 Tfft::Tspectrum resp(icoeff.size());
400 Tseries ampdirect(icoeff.size());
404 aff::Iterator<Tfft::Tspectrum> RC(resp);
405 aff::Browser<Tfft::Tspectrum> IC(icoeff);
406 aff::Browser<Tfft::Tspectrum> OC(ocoeff);
407 aff::Iterator<Tseries> AI(amp);
408 aff::Iterator<Tseries> ADI(ampdirect);
409 aff::Iterator<Tseries> PI(phase);
410 const double radtodegrees=180./3.1415926535897931159979634685441;
412 while(IC.valid() && OC.valid() && RC.valid())
415 *RC = ( (*OC) * std::conj(*IC) ) / ( std::norm(*IC) + damping );
416 if (AI.valid()) { *AI = std::abs(*RC); ++AI; }
417 if (PI.valid()) { *PI = -atan2(RC->imag(),RC->real())*radtodegrees; ++PI; }
419 if (ADI.valid()) { *ADI = (std::abs(*OC)/std::abs(*IC)); ++ADI; }
425 Tseries impresp=fft(resp, iwid2.dt);
431 std::string& outfile=impulseresponsefilename;
432 if (opt.
verbose) { cout <<
"open output file " << outfile << endl; }
436 std::ifstream file(outfile.c_str(),std::ios_base::in);
437 TFXX_assert((!file.good()),
"ERROR: output file exists!");
439 std::ofstream ofs(outfile.c_str());
440 datrw::osffstream os(ofs);
445 os << foutputtseries;
453 double T=iwid2.dt*iwid2.nsamples;
459 aff::Browser<Tseries> AI(amp);
460 aff::Browser<Tseries> ADI(ampdirect);
461 aff::Browser<Tseries> PI(phase);
462 aff::Browser<Tfft::Tspectrum> IC(icoeff);
463 aff::Browser<Tfft::Tspectrum> OC(ocoeff);
465 while(AI.valid() && PI.valid() && ADI.valid() && IC.valid() && OC.valid())
468 os << f <<
" " << *AI <<
" " << *PI <<
" " << *ADI <<
" ";
469 os <<
" " << abs(*IC) <<
" " << abs(*OC);
471 ++AI; ++PI; ++fidx; ++ADI; ++IC; ++OC;
ts::sff::SFFTimeSeries< Tseries > Ttimeseries
const char * keys[]
list of keys for filename specific parameters
fourier::fft::DRFFTWAFF Tfft
const char *const tracekey
key to select traces
std::string transformfile
aff::Series< double > Tseries