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
00066 ttsdata LocalRad(RComp.GetData());
00067 ttsdata LocalVer(VComp.GetData());
00068
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
00076 SubMean(LocalVer.begin(), LocalVer.end());
00077 SubMean(LocalRad.begin(), LocalRad.end());
00078
00079 ApplyWindow(LocalVer.begin(), LocalVer.end(), LocalVer.begin(), Steep());
00080 ApplyWindow(LocalRad.begin(), LocalRad.end(), LocalRad.begin(), Steep());
00081
00082 tcompdata RadSpec(LocalRad.size()/2+1);
00083 tcompdata VerSpec(LocalVer.size()/2+1);
00084
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
00095 tcomp cmaxelem = *max_element(VerSpec.begin(), VerSpec.end(),
00096 gplib::absLess<tcomp,tcomp>());
00097 cmaxelem *= conj(cmaxelem);
00098 cmaxelem *= c;
00099
00100 const double denom = 1./(4.0 * sigma*sigma);
00101
00102 transform(RadSpec.begin(), RadSpec.end(), VerSpec.begin(), RecSpec.begin(),
00103 CalcSpectralElement(cmaxelem));
00104
00105 const dcomp phaseshift(0, shift);
00106
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
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.;
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;
00127 const int maxpoints = Filter.size()/2;
00128
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);
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
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
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