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

Generated on Tue May 4 16:52:15 2010 for GPLIB++ by  doxygen 1.5.8