14 #include "spectrumsolver.h"
16 #include <gsl/gsl_sf.h>
17 #define lambertW0 gsl_sf_lambert_W0
19 SpectrumSolver::SpectrumSolver() {}
20 SpectrumSolver::~SpectrumSolver() {}
24 return -2 * loglikelifood + 2 * k;
28 return -2 * loglikelifood + 2 * (k + 1) * n / (
double)(n - k - 2);
32 return -2 * loglikelifood + 2 * k * log(log(n) / log(2.0));
36 return -loglikelifood + k * log(n) / 2.0;
40 SpectrumSolver::genIFFT(
const std::vector<std::complex<double> >& wavein) {
41 m_ifftN->exec(wavein, m_ifft);
42 int n = wavein.size();
44 std::complex<double> *pifft = &m_ifft[0];
45 for(
unsigned int i = 0; i < n; i++) {
53 double windowlength, std::vector<double> &window) {
54 double wk = 1.0 / windowLength(t, t0, windowlength);
56 for(
int i = 0; i < t; i++) {
57 window[i] = windowfunc((i + t0) * wk);
61 SpectrumSolver::exec(
const std::vector<std::complex<double> >& memin, std::vector<std::complex<double> >& memout,
62 int t0,
double torr, FFT::twindowfunc windowfunc,
double windowlength)
throw (
XKameError&) {
63 windowlength = std::max(0.0, windowlength);
64 unsigned int t = memin.size();
65 unsigned int n = memout.size();
66 if (m_ifft.size() != n) {
67 m_fftN.reset(
new FFT(-1, n));
68 m_ifftN.reset(
new FFT(1, n));
74 genSpectrum(memin, memout, t0, torr, windowfunc, windowlength);
78 double wlen = windowLength(t, t0, windowlength);
79 int idx1 = std::max(0, std::min((
int)memin.size() - 1, -t0 + (int)lrint(wlen / 2.0)));
80 int idx0 = std::min(std::max(0, -t0 - (
int)lrint(wlen / 2.0)), idx1);
81 std::vector<std::complex<double> > memin1(idx1 + 1 - idx0);
82 for(
unsigned int i = 0; i < memin1.size(); i++)
83 memin1[i] = memin[i + idx0];
85 genSpectrum(memin1, memout, t0, torr, windowfunc, 1.0);
88 std::sort(m_peaks.begin(), m_peaks.end(), std::greater<std::pair<double, double> >());
93 SpectrumSolver::autoCorrelation(
const std::vector<std::complex<double> >&wave,
94 std::vector<std::complex<double> >&corr) {
98 m_ifftRX.reset(
new FFT(1, len));
100 std::vector<std::complex<double> > wavezf(
m_fftRX->length(), 0.0), corrzf(
m_fftRX->length());
101 std::copy(wave.begin(), wave.end(), wavezf.begin());
103 for(
int i = 0; i < corrzf.size(); i++)
104 wavezf[i] = std::norm(corrzf[i]);
105 m_ifftRX->exec(wavezf, corrzf);
106 corr.resize(wave.size());
107 double normalize = 1.0 / (corr.size() *
m_fftRX->length());
108 for(
int i = 0; i < corr.size(); i++) {
109 corr[i] = corrzf[i] * normalize;
114 const std::vector<double>& psd, std::vector<std::complex<double> >& waveout,
115 double tol,
bool powfit, FFT::twindowfunc windowfunc) {
116 int t = wavein.size();
117 int n = waveout.size();
120 t0a += (-t0a / n + 1) * n;
122 std::vector<std::complex<double> > wavezf(n, 0.0);
123 for(
int i = 0; i < t; i++) {
124 int j = (t0a + i) % n;
125 wavezf[j] = wavein[i];
127 m_fftN->exec(wavezf, waveout);
130 for(
int i = 0; i < n; i++) {
131 std::complex<double> z = waveout[i];
132 waveout[i] = z * sqrt(psd[i] / std::norm(z));
136 std::vector<double> weight;
137 window(t, origin, windowfunc, 1.0, weight);
139 double sigma20 = 0.0, sigma2 = 0.0, coeff = 1.0;
140 for(
int it = 0; it < 20; it++) {
141 double ns2 =
stepLSPE(wavein, origin, psd, waveout, powfit, coeff, weight);
144 dbgPrint(formatString(
"LSPE: err=%g, coeff=%g, it=%u\n", ns2, coeff, it));
146 if((it > 3) && (sigma2 - ns2 < sigma20 * tol)) {
155 const std::vector<double>& psd, std::vector<std::complex<double> >& waveout,
156 bool powfit,
double &coeff,
const std::vector<double> &weight) {
157 int t = wavein.size();
158 int n = waveout.size();
161 t0a += (-t0a / n + 1) * n;
166 for(
int i = 0; i < t; i++) {
167 double w = weight[i];
168 int j = (t0a + i) % n;
169 std::complex<double> z = m_ifft[j];
170 den += std::norm(z) * w;
171 nom += std::real(std::conj(wavein[i]) * z) * w;
176 std::vector<std::complex<double> > zfin(n, 0.0), zfout(n);
179 for(
int i = 0; i < t; i++) {
180 double w = weight[i];
182 int j = (t0a + i) % n;
183 std::complex<double> z = dcoeff * m_ifft[j] - wavein[i];
185 sigma2 += std::norm(z) * w;
187 m_fftN->exec(zfin, zfout);
188 double sor = 1.0 / sumw;
189 double wdiag = dcoeff * sor * sumw;
190 for(
int i = 0; i < n; i++) {
191 std::complex<double> z = - (zfout[i] - waveout[i] * wdiag);
192 waveout[i] = coeff * z * sqrt(psd[i] / std::norm(z));
198 SpectrumSolver::windowLength(
int t,
int t0,
double windowlength) {
199 return 2.0 * (std::max(-t0, (
int)t + t0) * windowlength);
204 int t = memin.size();
207 std::vector<std::complex<double> > zfin(n), zfft(n);
208 std::fill(zfin.begin(), zfin.end(), std::complex<double>(0.0));
209 for(
int i = 0; i < t; i++) {
210 zfin[i % n] = memin[i];
212 m_fftN->exec(zfin, zfft);
214 double ssum = 0.0, s2sum = 0.0;
215 for(
int i = 0; i < n; i++) {
216 double s = std::abs(zfft[i]);
220 double num = ssum*ssum/s2sum/n*t;
226 FFTSolver::genSpectrum(
const std::vector<std::complex<double> >& fftin, std::vector<std::complex<double> >& fftout,
227 int t0,
double , FFT::twindowfunc windowfunc,
double windowlength) {
228 unsigned int t = fftin.size();
229 unsigned int n = fftout.size();
232 t0a += (-t0a / n + 1) * n;
234 std::vector<double> weight;
235 window(t, t0, windowfunc, windowlength, weight);
236 std::fill(m_ifft.begin(), m_ifft.end(), std::complex<double>(0.0));
237 std::vector<std::complex<double> > zffftin(n, 0.0), fftout2(n);
238 for(
int i = 0; i < t; i++) {
239 int j = (t0a + i) % n;
240 m_ifft[j] = fftin[i] * weight[i];
241 zffftin[j] = m_ifft[j] * (double)(t0 + i) * std::complex<double>(0, -1);
243 m_fftN->exec(m_ifft, fftout);
244 m_fftN->exec(zffftin, fftout2);
247 std::vector<double> dy(n);
248 for(
int i = 0; i < n; i++) {
249 dy[i] = std::real(fftout2[i] * std::conj(fftout[i]));
251 for(
int ip = 0; ip < n; ip++) {
252 int in = (ip + 1) % n;
253 if((dy[ip] > 0) && (dy[in] < 0)) {
254 double dx = - dy[ip] / (dy[in] - dy[ip]);
256 if((dx >= 0) && (dx <= 1.0)) {
266 double r = std::abs(fftout[ip] * (1 - dx) + fftout[in] * dx);
267 m_peaks.push_back(std::pair<double, double>(r, dx + ip));
273 MEMStrict::~MEMStrict() {
277 MEMStrict::setup(
unsigned int t,
unsigned int n) {
278 if (m_lambda.size() != t) {
279 m_fftT.reset(
new FFT(-1, t));
281 m_accumDYFT.resize(t);
287 MEMStrict::solveZ(
double tol) {
288 unsigned int size = m_accumDYFT.size();
289 std::vector<double> dy2(size);
290 std::vector<double> &g2(m_accumG2);
292 for(
unsigned int i = 0; i < size; i++) {
293 dy2[i] = std::norm(m_accumDYFT[i]);
295 for(
unsigned int it = 0; it < lrint(log(size) + 2); it++) {
296 double k = 2 * m_accumZ * m_accumZ;
297 for(
unsigned int i = 0; i < size; i++) {
298 g2[i] = lambertW0(k * dy2[i]) * 0.5;
301 for(
unsigned int i = 0; i < size; i++) {
304 double err = fabs(nsumz - m_accumZ) / nsumz;
314 MEMStrict::genSpectrum(
const std::vector<std::complex<double> >& memin, std::vector<std::complex<double> >& memout,
315 int t0,
double tol, FFT::twindowfunc ,
double ) {
316 int t = memin.size();
317 int n = memout.size();
319 t0 += (-t0 / n + 1) * n;
321 double sqrtpow = 0.0;
322 for(
unsigned int i = 0; i < memin.size(); i++)
323 sqrtpow += std::norm(memin[i]);
324 sqrtpow = sqrt(sqrtpow);
325 double err = sqrtpow;
327 for(
double sigma = sqrtpow / 4.0; sigma < sqrtpow; sigma *= 1.2) {
329 std::fill(m_accumDYFT.begin(), m_accumDYFT.end(), std::complex<double>(0.0));
330 std::fill(m_ifft.begin(), m_ifft.end(), std::complex<double>(0.0));
331 std::fill(m_lambda.begin(), m_lambda.end(), std::complex<double>(0.0));
332 std::fill(m_accumDY.begin(), m_accumDY.end(), std::complex<double>(0.0));
333 std::fill(m_accumG2.begin(), m_accumG2.end(), 0.0);
335 double oerr = sqrtpow;
337 for(it = 0; it < 50; it++) {
338 err = stepMEM(memin, memout, alpha, sigma, t0, tol);
339 if(err < tol * sqrtpow) {
342 if(err > sqrtpow * 1.1) {
345 if(err > oerr * 1.0) {
350 if(err < tol * sqrtpow) {
351 dbgPrint(formatString(
"MEM: Converged w/ sigma=%g, alpha=%g, err=%g, it=%u\n", sigma, alpha, err, it));
352 double osqrtpow = 0.0;
353 for(
unsigned int i = 0; i < memout.size(); i++)
354 osqrtpow += std::norm(memout[i]);
355 osqrtpow = sqrt(osqrtpow / n);
356 dbgPrint(formatString(
"MEM: Pout/Pin=%g\n", osqrtpow/sqrtpow));
360 dbgPrint(formatString(
"MEM: Failed w/ sigma=%g, alpha=%g, err=%g, it=%u\n", sigma, alpha, err, it));
363 if(err >= tol * sqrtpow) {
364 dbgPrint(formatString(
"MEM: Use ZF-FFT instead.\n"));
365 std::fill(m_ifft.begin(), m_ifft.end(), std::complex<double>(0.0));
366 for(
unsigned int i = 0; i < t; i++) {
367 m_ifft[(t0 + i) % n] = memin[i];
369 m_fftN->exec(m_ifft, memout);
372 std::vector<std::complex<double> > zffftin(n), fftout2(n);
373 for(
int i = 0; i < n; i++) {
374 zffftin[i] = m_ifft[i] * (double)((i >= n/2) ? (i - n) : i) * std::complex<double>(0, -1);
378 m_fftN->exec(zffftin, fftout2);
379 std::vector<double> dy(n);
380 for(
int i = 0; i < n; i++) {
381 dy[i] = std::real(fftout2[i] * std::conj(memout[i]));
383 for(
int ip = 0; ip < n; ip++) {
384 int in = (ip + 1) % n;
385 if((dy[ip] > 0) && (dy[in] < 0)) {
386 double dx = - dy[ip] / (dy[in] - dy[ip]);
387 if((dx >= 0) && (dx <= 1.0)) {
388 double r = std::abs(memout[ip] * (1 - dx) + memout[in] * dx);
389 m_peaks.push_back(std::pair<double, double>(r, dx + ip));
395 MEMStrict::stepMEM(
const std::vector<std::complex<double> >& memin, std::vector<std::complex<double> >& memout,
396 double alpha,
double sigma,
int t0,
double tol) {
397 unsigned int n = m_ifft.size();
398 unsigned int t = memin.size();
399 double isigma = 1.0 / sigma;
400 std::vector<std::complex<double> > &lambdaZF(m_ifft);
401 std::fill(lambdaZF.begin(), lambdaZF.end(), std::complex<double>(0.0));
402 std::complex<double> *plambda = &m_lambda[0];
403 for(
unsigned int i = 0; i < t; i++) {
404 lambdaZF[(t0 + i) % n] = *plambda * isigma;
407 m_ifftN->exec(lambdaZF, memout);
408 std::vector<double> pfz(n);
410 double *ppfz = &pfz[0];
411 std::complex<double> *pmemout = &memout[0];
412 for(
unsigned int i = 0; i < n; i++) {
413 *ppfz = exp(std::norm(*pmemout));
417 double k = 2.0 * sigma / sumz * n;
419 pmemout = &memout[0];
420 for(
unsigned int i = 0; i < n; i++) {
421 double p = k * *ppfz++;
422 *pmemout = std::conj(*pmemout) * p;
427 k = alpha / t / sigma / 2;
429 const std::complex<double> *pmemin = &memin[0];
430 std::complex<double> *pout = &m_accumDY[0];
431 for(
unsigned int i = 0; i < t; i++) {
432 std::complex<double> *pifft = &m_ifft[(t0 + i) % n];
433 std::complex<double> dy = *pmemin - *pifft;
435 err += std::norm(dy);
441 m_fftT->exec(m_accumDY, m_accumDYFT);
444 pout = &m_accumDYFT[0];
445 for(
unsigned int i = 0; i < t; i++) {
446 double p = k * sqrt(m_accumG2[i] / (std::norm(*pout)));
447 *pout = std::conj(*pout) * p;
450 m_fftT->exec(m_accumDYFT, m_lambda);