RecCalc.cpp

Go to the documentation of this file.
00001 #include "RecCalc.h"
00002 #include "types.h"
00003 #include "convert.h"
00004 #include "miscfunc.h"
00005 #include "IterDecon.h"
00006 #include <iostream>
00007 #include <fstream>
00008 #include <algorithm>
00009 #include <boost/bind.hpp>
00010 #include <boost/cast.hpp>
00011 #include <boost/filesystem.hpp>
00012 #include <numeric>
00013 #include <functional>
00014 #include <cassert>
00015 #include <gsl/gsl_math.h>
00016 #include <sys/types.h>
00017 #include <unistd.h>
00018 #include "statutils.h"
00019 #include "WFunc.h"
00020 #include "CRFSpecElement.h"
00021 #include "SeisTools.h"
00022 #include "Adaptors.h"
00023 
00024 using namespace std;
00025 
00026 RecCalc::RecCalc(const int myshift, const double myomega, const double mysigma,
00027     const double myc, bool multicalc, const trfmethod themethod) :
00028   method(themethod), Spectrum(multicalc), c(myc), omega(myomega),
00029       sigma(mysigma), shift(myshift), normalize(false)
00030   {
00031 
00032   }
00033 
00034 RecCalc::RecCalc(const RecCalc &Old) :
00035   method(Old.method), Spectrum(Old.Spectrum), c(Old.c), omega(Old.omega),
00036       sigma(Old.sigma), shift(Old.shift), normalize(Old.normalize),
00037       RadComp(Old.RadComp), VerComp(Old.VerComp)
00038   {
00039 
00040   }
00041 
00042 RecCalc& RecCalc::operator=(const RecCalc& source)
00043   {
00044     if (this == &source) return *this;
00045     method = source.method;
00046     Spectrum = source.Spectrum;
00047     c = source.c;
00048     omega = source.omega;
00049     sigma = source.sigma;
00050     shift = source.shift;
00051     normalize = source.normalize;
00052     RadComp = source.RadComp;
00053     VerComp = source.VerComp;
00054     return *this;
00055   }
00056 
00057 RecCalc::~RecCalc()
00058   {
00059   }
00060 
00061 void RecCalc::SpectralDivision(const SeismicDataComp &RComp,
00062     const SeismicDataComp &VComp, SeismicDataComp &Receiver)
00063   {
00064     const double omegastep = 2. * PI/(RComp.GetDt() * RComp.GetData().size());
00065     // Make local copies for trimming an mean removal
00066     ttsdata LocalRad(RComp.GetData());
00067     ttsdata LocalVer(VComp.GetData());
00068     // Make both components the same length 
00069     if (LocalRad.size() > LocalVer.size())
00070       LocalRad.erase(LocalRad.end() - (LocalRad.size() - LocalVer.size()),
00071           LocalRad.end());
00072     else if (LocalVer.size() > LocalRad.size())
00073       LocalVer.erase(LocalVer.end() - (LocalVer.size() - LocalRad.size()),
00074           LocalVer.end());
00075     //remove the mean
00076     SubMean(LocalVer.begin(), LocalVer.end());
00077     SubMean(LocalRad.begin(), LocalRad.end());
00078     //apply a window function for spectral calculation
00079     ApplyWindow(LocalVer.begin(), LocalVer.end(), LocalVer.begin(), Steep());
00080     ApplyWindow(LocalRad.begin(), LocalRad.end(), LocalRad.begin(), Steep());
00081     //assign space for spectra
00082     tcompdata RadSpec(LocalRad.size()/2+1);
00083     tcompdata VerSpec(LocalVer.size()/2+1);
00084     //calculate spetrca
00085     Spectrum.CalcSpectrum(LocalRad.begin(), LocalRad.end(), RadSpec.begin(),
00086         RadSpec.end());
00087     Spectrum.CalcSpectrum(LocalVer.begin(), LocalVer.end(), VerSpec.begin(),
00088         VerSpec.end());
00089     tcompdata RecSpec(RadSpec.size(), 0);
00090 
00091     typedef tcompdata::iterator tcomit;
00092 
00093     Receiver.GetData().assign(LocalRad.size(), 0);
00094     // determine the waterlevel threshold from the maximum vertical spectrum and the waterlevel parameter c
00095     tcomp cmaxelem = *max_element(VerSpec.begin(), VerSpec.end(),
00096         gplib::absLess<tcomp,tcomp>());
00097     cmaxelem *= conj(cmaxelem);
00098     cmaxelem *= c;
00099     // the denominator for the gaussian filter
00100     const double denom = 1./(4.0 * sigma*sigma);
00101     //calculate the spectrum of the receiver function
00102     transform(RadSpec.begin(), RadSpec.end(), VerSpec.begin(), RecSpec.begin(),
00103     CalcSpectralElement(cmaxelem));
00104     //determine the phaseshift for the desired shift in points
00105     const dcomp phaseshift(0, shift);
00106     // apply the gaussian filter
00107     for (tcomit recit = RecSpec.begin(); recit < RecSpec.end(); ++recit)
00108       {
00109         double freq = omegastep * distance(RecSpec.begin(), recit);
00110         *recit *= exp(- (freq*freq)*denom);
00111         *recit *= exp( -phaseshift * freq);
00112       }
00113     //transform receiver function spectrum back to time domain
00114     Spectrum.CalcTimeSeries(RecSpec.begin(), RecSpec.end(), Receiver.GetData().begin(), Receiver.GetData().end());
00115   }
00116 
00117 void RecCalc::IterativeDeconvolution(const SeismicDataComp &RComp,
00118     const SeismicDataComp &VComp, SeismicDataComp &Receiver)
00119   {
00120     gplib::rvec Filter(RComp.GetData().size());
00121     const double dt = RComp.GetDt();
00122     double normfactor = 1.; // /(sigma * sqrt(2.* acos(-1.)));
00123     const int shiftpoints = boost::numeric_cast<int>(shift/dt);
00124     const double variancesq = sigma*dt * sigma*dt;
00125     const unsigned int maxit = 100;
00126     const double minimprove = 1e-4; // we want to stop when the improvement is less than 0.1%
00127     const int maxpoints = Filter.size()/2; //we store it in a signed variable to avoid compiler warning for the loop below 
00128     //the loop index HAS TO BE SIGNED ! 
00129     for (int i = 0; i <= maxpoints; ++i)
00130       {
00131         Filter(i) = normfactor * exp( -pow((i-shiftpoints),2.) * variancesq);
00132         Filter(Filter.size() -i-1) = normfactor * exp( -pow((-i-1-shiftpoints),2.) * variancesq);
00133       }
00134 
00135     gplib::rvec RadFilter(RComp.GetData().size()), VerFilter(VComp.GetData().size());
00136     copy(RComp.GetData().begin(),RComp.GetData().end(),RadFilter.begin());
00137     copy(VComp.GetData().begin(),VComp.GetData().end(),VerFilter.begin());
00138     Convolve(RadFilter,Filter,RadFilter);
00139     Convolve(VerFilter,Filter,VerFilter);
00140     gplib::rvec Current(RadFilter), Output(RadFilter);
00141 
00142     IterDecon Decon(VerFilter.size());
00143     const double power = ublas::prec_inner_prod(RadFilter,RadFilter);
00144     double error = power;
00145     double lasterror = 1.;
00146     double improvement = 1.;
00147     unsigned int iter = 0;
00148     while (improvement> minimprove && iter < maxit)
00149       {
00150         Decon.AdaptFilter(VerFilter,Current);
00151         Decon.CalcOutput(VerFilter,Output);
00152 
00153         Current = RadFilter-Output;
00154         error = ublas::prec_inner_prod(Current,Current) /power;
00155         improvement = lasterror - error;
00156         lasterror = error;
00157         ++iter;
00158       }
00159     Convolve(Decon.GetWeights(),Filter,Current); //we re-use current to store the filtered weights, to save another object
00160     Receiver.GetData().assign(Current.size(),0);
00161     copy(Current.begin(),Current.end(),Receiver.GetData().begin());
00162   }
00163 
00164 void RecCalc::CalcRecData(const SeismicDataComp &RadComp,
00165     const SeismicDataComp &VerComp, SeismicDataComp &Receiver)
00166   {
00167     Receiver.CopyHeader(RadComp);
00168     switch (method)
00169       {
00170     case iterdecon:
00171       IterativeDeconvolution(RadComp, VerComp, Receiver);
00172       break;
00173     case specdiv:
00174       SpectralDivision(RadComp, VerComp, Receiver);
00175       break;
00176       }
00177     // set parameters for the timeseries object
00178     Receiver.SetB(-shift);
00179     Receiver.SetDt(RadComp.GetDt());
00180     if (normalize)
00181       {
00182         Normalize(Receiver.GetData());
00183       }
00184   }
00185 
00186 void RecCalc::CalcRecSynth(const std::string &filename, ResPkModel &Model,
00187     SeismicDataComp &Receiver, const bool cleanfiles)
00188   {
00189     SynthPreParallel(filename, Model, Receiver, cleanfiles);
00190     SynthSafeParallel(filename, Model, Receiver, cleanfiles);
00191     SynthPostParallel(filename, Model, Receiver, cleanfiles);
00192   }
00193 
00194 void RecCalc::SynthPreParallel(const std::string &filename, ResPkModel &Model,
00195     SeismicDataComp &Receiver, const bool cleanfiles)
00196   {
00197     Model.WriteRunFile(filename);
00198     Model.WriteData(filename+".mod");
00199   }
00200 void RecCalc::SynthSafeParallel(const std::string &filename, ResPkModel &Model,
00201     SeismicDataComp &Receiver, const bool cleanfiles)
00202   {
00203     system((filename).c_str());
00204     //system(("./iter"+filename).c_str());
00205 
00206     RadComp.GetData(filename+".mod_sp.r");
00207     VerComp.GetData(filename+".mod_sp.z");
00208     Receiver = RadComp;
00209     CalcRecData(RadComp, VerComp, Receiver);
00210   }
00211 
00212 void RecCalc::SynthPostParallel(const std::string &filename, ResPkModel &Model,
00213     SeismicDataComp &Receiver, const bool cleanfiles)
00214   {
00215     if (cleanfiles)
00216       {
00217         system(("rm "+filename+"*").c_str());
00218       }
00219   }
00220 

Generated on Fri Jul 4 15:30:21 2008 for GPLIB++ by  doxygen 1.5.5