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