STFINV library: seek source wavelet correction filter
stfinvfourier.cc
Go to the documentation of this file.
1 
44 #define STFINV_STFINVFOURIER_CC_VERSION \
45  "STFINV_STFINVFOURIER_CC V1.5"
46 
47 #include <sstream>
48 #include <cmath>
49 #include <stfinv/stfinvfourier.h>
52 #include <stfinv/debug.h>
53 #include <aff/subarray.h>
54 #include <aff/slice.h>
55 #include <aff/arrayoperators.h>
56 
57 namespace stfinv {
58 
74  const stfinv::Waveform& stf,
75  const stfinv::Tvectorofpairs& pairs,
76  const std::string& parameters)
77  :Tbase(triples, stf, pairs, parameters)
78  {
79  this->initialize();
80  } // STFFourierDomainEngine::STFFourierDomainEngine
81 
82  /*----------------------------------------------------------------------*/
83 
99  const stfinv::Waveform& stf,
100  const std::string& parameters)
101  :Tbase(triples, stf, parameters)
102  {
103  this->initialize();
104  } // STFFourierDomainEngine::STFFourierDomainEngine
105 
106  /*----------------------------------------------------------------------*/
107 
108  void STFFourierDomainEngine::help(std::ostream& os) const
109  {
111  } // void STFFourierDomainEngine::help(std::ostream& os) const
112 
113  /*----------------------------------------------------------------------*/
114 
115  void STFFourierDomainEngine::usage(std::ostream& os) const
116  {
118  } // void STFFourierDomainEngine::usage(std::ostream& os) const
119 
120 
121  /*----------------------------------------------------------------------*/
122 
123  const char* STFFourierDomainEngine::name() const
124  {
125  return("STFFourierDomainEngine");
126  } // const char const* STFFourierDomainEngine::name() const
127 
128  /*----------------------------------------------------------------------*/
129 
135  void STFFourierDomainEngine::classhelp(std::ostream& os)
136  {
138  } // void STFFourierDomainEngine::classhelp(std::ostream& os)
139 
140  /*----------------------------------------------------------------------*/
141 
147  void STFFourierDomainEngine::classusage(std::ostream& os)
148  {
150  os << std::endl;
151  Tbase::classusage(os);
152  } // void STFFourierDomainEngine::classusage(std::ostream& os)
153 
154  /*----------------------------------------------------------------------*/
155 
192  {
193  // extract parameter values
194  // ------------------------
195  // padding factor
196  double padfactor;
197  {
198  std::istringstream is(this->parameter("fpad","1.5"));
199  is >> padfactor;
200  }
201  STFINV_assert(padfactor >= 1.,
202  "ERROR: parameter for option \"fpad\" not larger or equal 1");
203  // flag: use power of two
204  bool poweroftwo=(this->parameter("fpow2","false")=="true");
205  // flag: use integer multiples of divisor
206  bool divisorset=this->parameterisset("fdiv");
207  // number of samples shall be integer power of divisor
208  unsigned int divisor=1;
209  if (divisorset)
210  {
211  std::istringstream is (this->parameter("fdiv","100"));
212  is >> divisor;
213  STFINV_assert(divisor > 0,
214  "ERROR: parameter for option \"fdiv\" not larger than 0");
215  }
216 
217  // define number of samples to be used by Fourier engine
218  // -----------------------------------------------------
219  // use at least the number of samples sepcified by the padfactor
220  unsigned int nsamples=padfactor*this->nsamples();
221  if (nsamples<this->nsamples()) { nsamples=this->nsamples(); }
222  // power of two has precendence
223  if (poweroftwo)
224  {
225  unsigned int n=2;
226  while (n<nsamples) { n *= 2; }
227  nsamples=n;
228  }
229  else if (divisorset)
230  {
231  unsigned int rest=nsamples % divisor;
232  nsamples -= rest;
233  nsamples += divisor;
234  } // if (poweroftwo) or (divisorset)
235 
236  // allocate workspace by creating engines
237  // --------------------------------------
238  Mfftengineinput=fourier::fft::DRFFTWAFFArrayEngine(
239  2*this->nreceivers()+this->npairs(),
240  nsamples);
241  Mfftengineoutput=fourier::fft::DRFFTWAFFArrayEngine(
242  1+this->nreceivers()+this->npairs(),
243  nsamples);
244  Mfftenginestf=fourier::fft::DRFFTWAFFArrayEngine(this->stfseries(),
245  this->stfspec());
246 
247  // set time shift for STF if requested
248  // -----------------------------------
249  {
250  std::istringstream is(this->parameter("tshift","0."));
251  is >> Mtshift;
252  }
253  Mapplyshift=this->parameterisset("tshift");
254 
255  // taper definition
256  // ----------------
257  {
258  std::istringstream is(stfinv::tools::secomtospace(
259  this->parameter("irtap","0.,1.,2.,3.")));
260  is >> Mtt1 >> Mtt2 >> Mtt3 >> Mtt4;
261  }
262  Mapplystftaper=this->parameterisset("irtap");
263  STFINV_assert((Mtt1<=Mtt2) && (Mtt2<=Mtt3) && (Mtt3<=Mtt4),
264  "ERROR: taper definition times not in increasing order");
265 
266  STFINV_debug(Mdebug&1, "STFFourierDomainEngine::initialize()",
267  STFINV_value(this->nsamples()) << "\n " <<
268  STFINV_value(padfactor) << "\n " <<
269  STFINV_value(divisor) << "\n " <<
270  STFINV_value(nsamples) << "\n " <<
271  STFINV_value(Mapplyshift) << "\n " <<
272  STFINV_value(Mtshift) << "\n " <<
273  STFINV_value(Mapplystftaper) << "\n " <<
274  STFINV_value(Mtt1) << "\n " <<
275  STFINV_value(Mtt2) << "\n " <<
276  STFINV_value(Mtt3) << "\n " <<
277  STFINV_value(Mtt4));
278  } // void STFFourierDomainEngine::initialize()
279 
280  /*----------------------------------------------------------------------*/
281 
294  {
295  this->getinput();
296  Mfftengineinput.r2c();
297  Mfftengineoutput.series()=0.;
298  } // void STFFourierDomainEngine::fftinput()
299 
300  /*----------------------------------------------------------------------*/
301 
316  {
317  if (this->Mapplystftaper) { this->taperstf(); }
318  this->convolve();
319  if (Mapplyshift) { this->stfshift(); }
320  Mfftengineoutput.c2r();
321  this->putoutput();
322  } // void STFFourierDomainEngine::fftoutput()
323 
324  /*----------------------------------------------------------------------*/
325 
328  {
329  TAspectrum inspecarray=Mfftengineinput.spectrum();
330  TAspectrum subarray=aff::subarray(inspecarray)()(0,this->nreceivers()-1);
331  subarray.shape().setfirst(0,0);
332  subarray.shape().setfirst(1,0);
333  return(subarray);
334  } // STFFourierDomainEngine::TAspectrum STFFourierDomainEngine::recordingspec() const
335 
336  /*----------------------------------------------------------------------*/
337 
340  {
341  TAspectrum inspecarray=Mfftengineinput.spectrum();
342  TAspectrum subarray=aff::subarray(inspecarray)()(this->nreceivers(),
343  (2*this->nreceivers())-1);
344  subarray.shape().setfirst(0,0);
345  subarray.shape().setfirst(1,0);
346  return(subarray);
347  } // STFFourierDomainEngine::TAspectrum STFFourierDomainEngine::syntheticspec() const
348 
349  /*----------------------------------------------------------------------*/
350 
352  {
353  return(Mfftengineoutput.spectrum(this->nreceivers()));
354  } // STFFourierDomainEngine::Tspectrum STFFourierDomainEngine::stfspec() const
355 
356  /*----------------------------------------------------------------------*/
357 
359  {
360  return(Mfftengineoutput.series(this->nreceivers()));
361  } // STFFourierDomainEngine::Tspectrum STFFourierDomainEngine::stfseries() const
362 
363  /*----------------------------------------------------------------------*/
364 
366  STFFourierDomainEngine::recordingcoeff(const unsigned int& i) const
367  {
369  STFFourierDomainEngine::TAspectrum slice=aff::slice(rec)(0,i);
370  slice.shape().setfirst(0,0);
371  slice.shape().setfirst(1,0);
372  return(slice);
373  } // STFFourierDomainEngine::recordingcoeff(const unsigned int& i) const
374 
375  /*----------------------------------------------------------------------*/
376 
378  STFFourierDomainEngine::syntheticcoeff(const unsigned int& i) const
379  {
380  STFINV_debug(Mdebug&8, "STFFourierDomainEngine::syntheticcoeff",
381  "i=" << i);
383  STFFourierDomainEngine::TAspectrum slice=aff::slice(syn)(0,i);
384  slice.shape().setfirst(0,0);
385  slice.shape().setfirst(1,0);
386  STFINV_debug(Mdebug&8, "STFFourierDomainEngine::syntheticcoeff",
387  "slice.first(0)=" << slice.first(0) << " " <<
388  "slice.last(0)=" << slice.last(0) << " "
389  "slice.first(1)=" << slice.first(1) << " " <<
390  "slice.last(1)=" << slice.last(1) << " ");
391  return(slice);
392  } // STFFourierDomainEngine::syntheticcoeff(const unsigned int& i) const
393 
394  /*----------------------------------------------------------------------*/
395 
397  STFFourierDomainEngine::stfcoeff(const unsigned int& i) const
398  {
400  return(stffft(i));
401  } // STFFourierDomainEngine::stfcoeff(const unsigned int& i) const
402 
403  /*----------------------------------------------------------------------*/
404 
405  double STFFourierDomainEngine::frequency(const unsigned int& i) const
406  {
407  return(static_cast<double>(i)/(this->dt()*Mfftengineinput.nsamples()));
408  } // double STFFourierDomainEngine::frequency(const unsigned int& i) const
409 
410  /*----------------------------------------------------------------------*/
411 
412  unsigned int STFFourierDomainEngine::nfreq() const
413  {
414  return(Mfftengineinput.nfrequencies());
415  } // unsigned int STFFourierDomainEngine::nfreq() const
416 
417  /*----------------------------------------------------------------------*/
418 
420  {
421  // clear workspace through reference
422  // (remark: return value sarray is a reference to an array addressing all
423  // samples of all time series contained in Mfftengineinput)
424  TAseries sarray=Mfftengineinput.series();
425  sarray=0.;
426 
427  // cycle through receivers
428  for (unsigned int i=0; i<this->nreceivers(); ++i)
429  {
430  // get references to time series in workspace
431  TAseries recordingref=Mfftengineinput.series(i);
432  TAseries syntheticref=Mfftengineinput.series(i+this->nreceivers());
433  // copyin function copies as many elements as possible
434  recordingref.copyin(this->recording(i));
435  syntheticref.copyin(this->synthetic(i));
436  } // for (unsigned int i=0; i<this->nreceivers(); ++i)
437 
438  // cycle through additional time series pairs
439  for (unsigned int i=0; i<this->npairs(); ++i)
440  {
441  // get references to time series in workspace
442  TAseries syntheticref=Mfftengineinput.series(i+2*this->nreceivers());
443  // copyin function copies as many elements as possible
444  syntheticref.copyin(this->series(i));
445  } // for (unsigned int i=0; i<this->npairs(); ++i)
446  } // void STFFourierDomainEngine::getinput()
447 
448  /*----------------------------------------------------------------------*/
449 
456  {
457  // scaling factor for source correction filter
458  double scalingstf=Mfftengineoutput.scale_series(this->dt());
459  // scaling factor for convolved synthetics
460  double scalingcs=Mfftengineoutput.scale_spectrum(this->dt())
461  *scalingstf;
462 
463  // cycle through receivers
464  for (unsigned int i=0; i<this->nreceivers(); ++i)
465  {
466  // get references to time series
467  stfinv::Tseries convolvedsynthetics=this->convolvedsynthetic(i);
468  // copyin function copies as many elements as possible
469  convolvedsynthetics.copyin(Mfftengineoutput.series(i)*scalingcs);
470  } // for (unsigned int i=0; i<this->nreceivers(); ++i)
471 
472  // copy stf too; get reference to series and use copyin
473  stfinv::Tseries stf=this->stf();
474  stf.copyin(Mfftengineoutput.series(this->nreceivers())
475  *scalingstf);
476 
477  // cycle through additional time series pairs
478  for (unsigned int i=0; i<this->npairs(); ++i)
479  {
480  // get references to time series
482  // copyin function copies as many elements as possible
483  convolvedseries.copyin(Mfftengineoutput.series(1+i+this->nreceivers())
484  *scalingcs);
485  } // for (unsigned int i=0; i<this->npairs(); ++i)
486 
487  } // void STFFourierDomainEngine::putoutput()
488 
489  /*----------------------------------------------------------------------*/
490 
504  {
507  =aff::subarray(Mfftengineoutput.spectrum())()(0,this->nreceivers()-1);
508  convolvedsynthetic.shape().setfirst(0,0);
509  convolvedsynthetic.shape().setfirst(1,0);
510  TAspectrum stfcoeff=this->stfspec();
511 
512  // cycle through all receivers
513  for (unsigned int i=0; i<this->nreceivers(); ++i)
514  {
515  for (unsigned int j=0; j<this->nfreq(); ++j)
516  {
518  } // for (unsigned int j=0; j<this->nfreq(); ++j)
519  } // for (unsigned int i=0; i<this->nreceivers(); ++i)
520 
521  // copy signals for additional pairs
522  if (this->npairs()>0)
523  {
524  // reference to input series Fourier coefficients of additional pairs
525  TAspectrum inspecarray=Mfftengineinput.spectrum();
526  TAspectrum seriesspecarray
527  =aff::subarray(inspecarray)()(2*this->nreceivers(),
528  (2*this->nreceivers()
529  +this->npairs()-1));
530  seriesspecarray.shape().setfirst(0,0);
531  seriesspecarray.shape().setfirst(1,0);
532 
533  // reference to convolved series Fourier coefficients of additional
534  // pairs
536  =aff::subarray(Mfftengineoutput.spectrum())()(this->nreceivers()+1,
537  this->nreceivers()
538  +this->npairs());
539  convolvedseries.shape().setfirst(0,0);
540  convolvedseries.shape().setfirst(1,0);
541  // cycle through all pairs
542  for (unsigned int i=0; i<this->npairs(); ++i)
543  {
544  for (unsigned int j=0; j<this->nfreq(); ++j)
545  {
546  convolvedseries(j,i)=seriesspecarray(j,i)*stfcoeff(j);
547  } // for (unsigned int j=0; j<this->nfreq(); ++j)
548  } // for (unsigned int i=0; i<this->npairs(); ++i)
549  } // if (this->npairs()>0)
550 
551  } // void STFFourierDomainEngine::convolve()
552 
553  /*----------------------------------------------------------------------*/
554 
556  {
557  STFINV_debug(Mdebug&2, "STFFourierDomainEngine::stfshift()",
558  "apply time shift of " << Mtshift << " seconds");
561  *3.141592653589793115998*2.*Mtshift;
562  // STFINV_DUMP( sfac );
564  for (unsigned int j=0; j<this->nfreq(); ++j)
565  {
566  stffft(j) *= std::exp(sfac*this->frequency(j));
567  // STFINV_DUMP( std::exp(sfac*this->frequency(j)) );
568  } // for (unsigned int j=0; j<this->nfreq(); ++j)
569  } // void STFFourierDomainEngine::stfshift()
570 
571  /*----------------------------------------------------------------------*/
572 
578  {
579  STFINV_debug(Mdebug&16, "STFFourierDomainEngine::taperstf()",
581  if (this->Mapplystftaper)
582  {
583  // transform correction filter to time domain
584  Mfftenginestf.c2r();
585  Tfftengine::TAseries thestfseries=this->stfseries();
586  thestfseries *= Mfftenginestf.scale_series(this->dt());
587  // apply taper
588  /*
589  * Concept of application to periodic time series allowing for negative
590  * values of taper times:
591  *
592  * All samples between t2 and t3 remain unaltered. It is reasonable to
593  * process the taper starting at t3 passing t4 to t1 and then ending at
594  * t2. Behind this is the concept that time series are implicitely
595  * periodic in discrete Fourier transform.
596  */
597  // samples in series
598  int nsamples=thestfseries.size(0);
599  // duration of time series
600  double T=this->dt()*nsamples;
601  // make sure taper definition is not longer than time series.
602  STFINV_assert((this->Mtt4-this->Mtt1)<T,
603  "Taper width is larger than length of time series");
604  // set taper time values under conpect of periodic series
605  double tt3=this->Mtt3;
606  double tt4=this->Mtt4;
607  double tt1=this->Mtt1+T;
608  double tt2=this->Mtt2+T;
609  // sample to start at
610  int l3=int(std::floor(tt3/this->dt()));
611  int l2=int(std::ceil(tt2/this->dt()));
612  STFINV_debug(Mdebug&16, "STFFourierDomainEngine::taperstf()",
613  STFINV_value(T) << "\n " <<
614  STFINV_value(this->dt()) << "\n " <<
615  STFINV_value(nsamples) << "\n " <<
616  STFINV_value(tt3) << "\n " <<
617  STFINV_value(tt4) << "\n " <<
618  STFINV_value(tt1) << "\n " <<
619  STFINV_value(tt2) << "\n " <<
620  STFINV_value(l3) << "\n " <<
621  STFINV_value(l2));
622  for (int l=l3; l<=l2; ++l)
623  {
624  // time of sample
625  double t=l*this->dt();
626  // index to series
627  int rl = l%nsamples;
628  if (rl < 0) { rl += nsamples; }
629  STFINV_assert(((rl >= thestfseries.f(0)) &&
630  (rl <= thestfseries.l(0))),
631  "Index out of range. Internal programming error! "
632  "Report as bug!")
633  // taper factor
634  double factor=1.;
635  if ( (t>=tt3) && (t<=tt4) && (tt4>tt3) )
636  {
637  factor=0.5+0.5*cos(M_PI*(t-tt3)/(tt4-tt3));
638  }
639  else if ( (t>tt4) && (t<tt1) )
640  {
641  factor=0.;
642  }
643  else if ( (t>=tt1) && (t<=tt2) && (tt2>tt1) )
644  {
645  factor=0.5-0.5*cos(M_PI*(t-tt1)/(tt2-tt1));
646  }
647  // apply to series
648  thestfseries(rl) = thestfseries(rl)*factor;
649  STFINV_debug(Mdebug&16, "STFFourierDomainEngine::taperstf()",
650  STFINV_value(t) << " " <<
651  STFINV_value(l) << " " <<
652  STFINV_value(rl) << " " <<
653  STFINV_value(factor));
654  }
655  // transform correction filter to Fourier domain
656  Mfftenginestf.r2c();
657  this->stfspec() *= Mfftenginestf.scale_spectrum(this->dt());
658  } // if (this->Mapplystftaper)
659  } // void STFFourierDomainEngine::taperstf()
660 
661 } // namespace stfinv
662 
663 /* ----- END OF stfinvfourier.cc ----- */
bool parameterisset(const std::string &key) const
check is parameter was set by user
Definition: stfinvbase.cc:266
std::vector< stfinv::WaveformPair > Tvectorofpairs
Vector of pairs.
Definition: stfinvbase.h:125
unsigned int npairs() const
return number of additional signals to be convolved
Definition: stfinvbase.h:262
double Mtt4
time values defining taper.
Tfftengine::TAseries TAseries
type of array for time series values
double Mtt2
time values defining taper.
static void classhelp(std::ostream &os=std::cout)
print online help
unsigned int nreceivers() const
return number of receiver signals in use
Definition: stfinvbase.h:259
float Tvalue
Value type of samples.All references to time series samples in user workspace are based on this type...
Tfftengine Mfftenginestf
FFT processor for source time function correction filter.
double Mtt3
time values defining taper.
void fftinput()
copy input signals to workspace and transform input workspace to Fourier domain
Tfftengine::TAspectrum TAspectrum
type of array for Fourier transforms
suport debugging in libstfinv (prototypes)
Root namespace of library.
Definition: doxygen.txt:43
double Mtt1
time values defining taper.
bool Mapplyshift
true if shift must be applied
TAspectrum recordingcoeff(const unsigned int &i) const
return reference to Fourier coeffients of recorded data for frequency i
double Mtshift
time shift to be applied to STF in order to expose acausal parts
void stfshift()
apply time shift to stf prior to FFT to time domain
TAspectrum::Tvalue & stfcoeff(const unsigned int &i) const
return reference to Fourier coefficients of stf for frequency i
unsigned int nsamples() const
return number of samples used in time series
Definition: stfinvbase.h:256
void taperstf()
apply a time domain taper to the correction filter response.
std::string parameter(const std::string &key, const std::string &defvalue="false") const
return the value of a parameters
Definition: stfinvbase.cc:279
void convolve()
convolve synthetics with stf
void putoutput()
copy workspace time series for convolved synthetics and stf to user memory
virtual const char * name() const
return name of engine
TAspectrum syntheticspec() const
return reference to Fourier transform of synthetics
Tseries::Tcoc recording(const unsigned int &i) const
return recorded data at receiver i
Definition: stfinvbase.cc:303
Tseries::Tcoc series(const unsigned int &i) const
return synthetic data of pair i
Definition: stfinvbase.cc:327
TAseries stfseries() const
return reference to time series container of stf
#define STFINV_value(P)
report value in a sequence of output operators
Definition: debug.h:62
TAspectrum recordingspec() const
return reference to Fourier transform of recorded data
#define STFINV_assert(C, M)
Check an assertion and report by throwing an exception.
Definition: error.h:140
TAspectrum stfspec() const
return reference to Fourier transform of stf
static void classusage(std::ostream &os=std::cout)
print detailed description
Definition: stfinvbase.cc:227
int Mdebug
debug level
Definition: stfinvbase.h:336
void initialize()
initialize work space
Tseries::Tcoc synthetic(const unsigned int &i) const
return synthetic data at receiver i
Definition: stfinvbase.cc:311
Tseries convolvedseries(const unsigned int &i) const
return synthetic data convolved with stf for pair i
Definition: stfinvbase.cc:335
A class to store a single waveform. This will be used to pass the source correction filter...
Definition: stfinvbase.h:111
STFFourierDomainEngine(const stfinv::Tvectoroftriples &triples, const stfinv::Waveform &stf, const std::string &parameters)
Constructor.
double frequency(const unsigned int &i) const
return value of frequency i in Hz
std::string secomtospace(std::string s)
Tfftengine Mfftengineinput
combined FFT engine for recorded data and synthetics and additional time series
double dt() const
return sampling interval
Definition: stfinvbase.h:265
void getinput()
copy input time series for recorded data and synthetics to workspace
virtual void help(std::ostream &os=std::cout) const
print online help
a base class for all engines which operate in the Fourier domain (prototypes)
unsigned int nfreq() const
return number of frequencies in use
Abstract base class for engines to derive source correction filter.
Definition: stfinvbase.h:208
Tfftengine Mfftengineoutput
combined FFT engine for stf and convolved synthetics and additional convolved time series ...
virtual void usage(std::ostream &os=std::cout) const
print detailed description
char stfinvfourier_summary_usage[]
std::vector< stfinv::WaveformTriple > Tvectoroftriples
Vector of triples.
Definition: stfinvbase.h:132
bool Mapplystftaper
true if time domain taper should be applied to filter response.
TAspectrum syntheticcoeff(const unsigned int &i) const
return reference to Fourier coefficients of synthetics for frequency i
void fftoutput()
convolve synthetics with Fourier transform of stf and transform convolved synthetics and stf to time ...
Tseries convolvedsynthetic(const unsigned int &i) const
return synthetic data convolved with stf at receiver i
Definition: stfinvbase.cc:319
Tseries stf() const
return source correction filter series
Definition: stfinvbase.h:273
char stfinvfourier_description_usage[]
#define STFINV_debug(C, N, M)
produce debug output
Definition: debug.h:49
aff::Series< Tvalue > Tseries
Type of sample values.
Definition: stfinvbase.h:56
static void classusage(std::ostream &os=std::cout)
print detailed description