void addtoavgenergy(t_complex *list, real *result, int size, int tsteps) { int i; for (i = 0; i < size; i++) { result[i] += cabs2(list[i])/tsteps; } }
dmat *psd1d(const dmat *v, /**<[in] The data sequence*/ long nseg /**<[in] Number of overlapping segments*/ ){ long nx; long ncol; if(v->nx==1){ nx=v->ny; ncol=1; }else{ nx=v->nx; ncol=v->ny; } if(nseg<=1) nseg=1; const int lseg2=nx/(nseg+1); const int lseg=lseg2*2; dmat *psd=dnew(lseg2+1, ncol); cmat *hat=cnew(lseg, 1); //cfft2plan(hat, -1); for(long icol=0; icol<ncol; icol++){ double *ppsd=psd->p+icol*(lseg2+1); for(int iseg=0; iseg<nseg; iseg++){ double* p=v->p+icol*nx+iseg*lseg2; for(int ix=0; ix<lseg; ix++){ hat->p[ix]=p[ix]*W_J(ix, lseg2); } cfft2(hat, -1); ppsd[0]+=cabs2(hat->p[0]); for(int ix=1; ix<lseg2; ix++){ ppsd[ix]+=cabs2(hat->p[ix])+cabs2(hat->p[lseg-ix]); } ppsd[lseg2]+=cabs2(hat->p[lseg2]); } } double sumwt=0; for(int ix=0; ix<lseg; ix++){ sumwt+=pow(W_J(ix, lseg2), 2); } sumwt*=lseg*nseg; dscale(psd, 1./sumwt); cfree(hat); return psd; }
// HIGHPASS pzkContainer * t2hp(pzkContainer * pzk, real w0) { pzkContainer * f = createPzkContainer(pzk->nextPole, pzk->nextZero); uint i; complex tmp; f->amp = pzk->amp * pow(w0,(real)pzk->no_wz); f->no_wz = -pzk->no_wz; for( i = 0; i < pzk->nextPole; i++ ) { tmp.re = w0; tmp.im = 0; f->no_wz++; if( cisreal(pzk->poles[i]) ) { f->amp /= -pzk->poles[i].re; tmp.re /= pzk->poles[i].re; } else { tmp = cdiv(tmp, pzk->poles[i]); f->amp /= cabs2(pzk->poles[i]); f->no_wz++; } addPole(f, tmp); } for( i = 0; i < pzk->nextZero; i++ ) { tmp.re = w0; tmp.im = 0; f->no_wz--; if( cisreal(pzk->zeros[i]) ) { f->amp *= -pzk->zeros[i].re; tmp.re /= pzk->zeros[i].re; } else { tmp = cdiv(tmp, pzk->zeros[i]); f->amp *= cabs2(pzk->zeros[i]); f->no_wz--; } addZero(f, tmp); } f->type = highpass; return f; }
int mandel(double complex z) { int maxiter = 80; double complex c = z; for (int n = 0; n < maxiter; ++n) { if (cabs2(z) > 4.0) { return n; } z = z*z+c; } return maxiter; }
static int mandel(double cre, double cim, int MAX_ITER) { const float Z_MAX2 = 4.0; double zre = cre, zim = cim; int iter; for (iter = 0; iter < MAX_ITER; iter++) { double z1re, z1im; z1re = zre * zre - zim * zim; z1im = 2 * zre * zim; z1re += cre; z1im += cim; if (cabs2(z1re, z1im) > Z_MAX2) { return iter + 1; /* outside set */ } zre = z1re; zim = z1im; } return 0; /* inside set */ }
int PSDCalculator::calculatePowerSpectrum( double *input, int inputLen, double *output, int outputLen, bool removeMean, bool interpolateHoles, bool average, int averageLen, bool apodize, ApodizeFunction apodizeFxn, double gaussianSigma, PSDType outputType, double inputSamplingFreq) { if (outputLen != calculateOutputVectorLength(inputLen, average, averageLen)) { KstDebug::self()->log(QObject::tr("in PSDCalculator::calculatePowerSpectrum: received output array with wrong length."), KstDebug::Error); return -1; } if (outputLen != _prevOutputLen) { delete[] _a; delete[] _w; _awLen = outputLen*2; _prevOutputLen = outputLen; _a = new double[_awLen]; _w = new double[_awLen]; updateWindowFxn(apodizeFxn, gaussianSigma); } if ( (_prevApodizeFxn != apodizeFxn) || (_prevGaussianSigma != gaussianSigma) ) { updateWindowFxn(apodizeFxn, gaussianSigma); } int currentCopyLen, nsamples = 0; int i_samp, i_subset, ioffset; memset(output, 0, sizeof(double) * outputLen); bool done = false; for (i_subset = 0; !done; i_subset++) { // // overlapping average => i_subset*outputLen... // ioffset = i_subset * outputLen; // // only zero pad if we really have to. // It is better to adjust the last chunk's overlap... // if (ioffset + _awLen*5/4 < inputLen) { currentCopyLen = _awLen; // will copy a complete window. } else if (_awLen<inputLen) { // count the last one from the end. ioffset = inputLen-_awLen - 1; currentCopyLen = _awLen; // will copy a complete window. done = true; } else { currentCopyLen = inputLen - ioffset; // will copy a partial window. memset(&_a[currentCopyLen], 0, sizeof(double)*(_awLen - currentCopyLen)); // zero the leftovers. done = true; } double mean = 0.0; if (removeMean) { for (i_samp = 0; i_samp < currentCopyLen; i_samp++) { mean += input[i_samp + ioffset]; } mean /= (double)currentCopyLen; } // // apply the PSD options (removeMean, apodize, etc.) // separate cases for speed- although this shouldn't really matter - // the rdft should be the most time consuming step by far for any large data set... // if (removeMean && apodize && interpolateHoles) { for (i_samp = 0; i_samp < currentCopyLen; i_samp++) { _a[i_samp] = (kstInterpolateNoHoles(input, inputLen, i_samp + ioffset, inputLen) - mean)*_w[i_samp]; } } else if (removeMean && apodize) { for (i_samp = 0; i_samp < currentCopyLen; i_samp++) { _a[i_samp] = (input[i_samp + ioffset] - mean)*_w[i_samp]; } } else if (removeMean && interpolateHoles) { for (i_samp = 0; i_samp < currentCopyLen; i_samp++) { _a[i_samp] = kstInterpolateNoHoles(input, inputLen, i_samp + ioffset, inputLen) - mean; } } else if (apodize && interpolateHoles) { for (i_samp = 0; i_samp < currentCopyLen; i_samp++) { _a[i_samp] = kstInterpolateNoHoles(input, inputLen, i_samp + ioffset, inputLen)*_w[i_samp]; } } else if (removeMean) { for (i_samp = 0; i_samp < currentCopyLen; i_samp++) { _a[i_samp] = input[i_samp + ioffset] - mean; } } else if (apodize) { for (i_samp = 0; i_samp < currentCopyLen; i_samp++) { _a[i_samp] = input[i_samp + ioffset]*_w[i_samp]; } } else if (interpolateHoles) { for (i_samp = 0; i_samp < currentCopyLen; i_samp++) { _a[i_samp] = kstInterpolateNoHoles(input, inputLen, i_samp + ioffset, inputLen); } } else { for (i_samp = 0; i_samp < currentCopyLen; i_samp++) { _a[i_samp] = input[i_samp + ioffset]; } } nsamples += currentCopyLen; // // real discrete fourier transorm on _a. // rdft(_awLen, 1, _a); output[0] += _a[0] * _a[0]; output[outputLen-1] += _a[1] * _a[1]; for (i_samp = 1; i_samp < outputLen - 1; i_samp++) { output[i_samp] += cabs2(_a[i_samp * 2], _a[i_samp * 2 + 1]); } } double frequencyStep = 2.0*(double)inputSamplingFreq/(double)nsamples; double norm = 2.0/(double)nsamples*2.0/(double)nsamples; switch (outputType) { default: case PSDAmplitudeSpectralDensity: // amplitude spectral density (default) [V/Hz^1/2] norm /= frequencyStep; for (i_samp = 0; i_samp < outputLen; i_samp++) { output[i_samp] = sqrt(output[i_samp]*norm); } break; case PSDPowerSpectralDensity: // power spectral density [V^2/Hz] norm /= frequencyStep; for (i_samp = 0; i_samp < outputLen; i_samp++) { output[i_samp] *= norm; } break; case PSDAmplitudeSpectrum: // amplitude spectrum [V] for (i_samp = 0; i_samp < outputLen; i_samp++) { output[i_samp] = sqrt(output[i_samp]*norm); } break; case PSDPowerSpectrum: // power spectrum [V^2] for (i_samp = 0; i_samp < outputLen; i_samp++) { output[i_samp] *= norm; } break; } return 0; }
// BANDSTOP pzkContainer * t2bs(pzkContainer * pzk, real w0, real dw) { uint nop, noz, i; pzkContainer * f; const real w02 = w0*w0; complex tmp, beta, gamma, cw0, cdwp2; cw0.re = w0; cw0.im = 0; cdwp2.re = dw / 2; cdwp2.im = 0; noz = 2*pzk->nextZero; nop = 2*pzk->nextPole; if( pzk->no_wz > 0 ) { noz += pzk->no_wz; } if( pzk->no_wz < 0 ) { nop -= pzk->no_wz; } f = createPzkContainer(nop, noz); f->wz = w0; f->no_wz = -pzk->no_wz; f->amp = pzk->amp * pow(dw, (real)(pzk->no_wz)); gamma.re = 0; gamma.im = 0; if( pzk->no_wz > 0 ) { for( i = 0; i < pzk->no_wz; i++ ) { addZero(f, gamma); } } if( pzk->no_wz < 0 ) { for( i = 0; i < -pzk->no_wz; i++ ) { addPole(f, gamma); } } for( i = 0; i < pzk->nextPole; i++ ) { if( cisreal(pzk->poles[i]) ) { beta.re = cdwp2.re / pzk->poles[i].re; tmp.re = 1 - ( w02/(beta.re*beta.re) ); if( tmp.re >= 0 ) { tmp.re = sqrt( tmp.re ); gamma.im = 0; gamma.re = beta.re * (1 + tmp.re); addPole(f, gamma); gamma.re = beta.re * (1 - tmp.re); addPole(f, gamma); } else { tmp.im = sqrt( -tmp.re ); tmp.re = 1; gamma = cmul2( beta.re, tmp ); addPole(f, gamma); } f->amp /= -pzk->poles[i].re; f->no_wz++; } else { beta = cdiv(cdwp2, pzk->poles[i]); tmp = cdiv(cw0, beta); tmp = csqrt( csub2(1, cmlt(tmp, tmp)) ); gamma = cmlt(beta, cadd2(1, tmp)); addPole(f, gamma); gamma = cmlt(beta, csub2(1, tmp)); addPole(f, gamma); f->amp /= cabs2(pzk->poles[i]); f->no_wz += 2; } } for( i = 0; i < pzk->nextZero; i++ ) { if( cisreal(pzk->zeros[i]) ) { beta.re = cdwp2.re / pzk->zeros[i].re; tmp.re = 1 - ( w02/(beta.re*beta.re) ); if( tmp.re >= 0 ) { tmp.re = sqrt( tmp.re ); gamma.im = 0; gamma.re = beta.re * (1 + tmp.re); addZero(f, gamma); gamma.re = beta.re * (1 - tmp.re); addZero(f, gamma); } else { tmp.im = sqrt( -tmp.re ); tmp.re = 1; gamma = cmul2( beta.re, tmp ); addZero(f, gamma); } f->amp *= -pzk->zeros[i].re; f->no_wz--; } else { beta = cdiv(cdwp2, pzk->zeros[i]); tmp = cdiv(cw0, beta); tmp = csqrt( csub2(1, cmlt(tmp, tmp)) ); gamma = cmlt(beta, cadd2(1, tmp)); addZero(f, gamma); gamma = cmlt(beta, csub2(1, tmp)); addZero(f, gamma); f->amp *= cabs2(pzk->zeros[i]); f->no_wz -= 2; } } return f; }
double *bayestar_sky_map_toa_phoa_snr( long *npix, /* Input: number of HEALPix pixels. */ double gmst, /* Greenwich mean sidereal time in radians. */ int nifos, /* Input: number of detectors. */ const float (**responses)[3], /* Pointers to detector responses. */ const double **locations, /* Pointers to locations of detectors in Cartesian geographic coordinates. */ const double *toas, /* Input: array of times of arrival with arbitrary relative offset. (Make toas[0] == 0.) */ const double *phoas, /* Input: array of phases of arrival with arbitrary relative offset. (Make phoas[0] == 0.) */ const double *snrs, /* Input: array of SNRs. */ const double *w_toas, /* Input: sum-of-squares weights, (1/TOA variance)^2. */ const double *w1s, /* Input: first moments of angular frequency. */ const double *w2s, /* Input: second moments of angular frequency. */ const double *horizons, /* Distances at which a source would produce an SNR of 1 in each detector. */ double min_distance, double max_distance, int prior_distance_power) /* Use a prior of (distance)^(prior_distance_power) */ { long nside; long maxpix; long i; double d1[nifos]; double *P; gsl_permutation *pix_perm; double complex exp_i_phoas[nifos]; /* Hold GSL return values for any thread that fails. */ int gsl_errno = GSL_SUCCESS; /* Storage for old GSL error handler. */ gsl_error_handler_t *old_handler; /* Maximum number of subdivisions for adaptive integration. */ static const size_t subdivision_limit = 64; /* Subdivide radial integral where likelihood is this fraction of the maximum, * will be used in solving the quadratic to find the breakpoints */ static const double eta = 0.01; /* Use this many integration steps in 2*psi */ static const int ntwopsi = 16; /* Number of integration steps in cos(inclination) */ static const int nu = 16; /* Number of integration steps in arrival time */ static const int nt = 16; /* Rescale distances so that furthest horizon distance is 1. */ { double d1max; memcpy(d1, horizons, sizeof(d1)); for (d1max = d1[0], i = 1; i < nifos; i ++) if (d1[i] > d1max) d1max = d1[i]; for (i = 0; i < nifos; i ++) d1[i] /= d1max; min_distance /= d1max; max_distance /= d1max; } (void)w2s; /* FIXME: remove unused parameter */ for (i = 0; i < nifos; i ++) exp_i_phoas[i] = exp_i(phoas[i]); /* Evaluate posterior term only first. */ P = bayestar_sky_map_toa_adapt_resolution(&pix_perm, &maxpix, npix, gmst, nifos, locations, toas, w_toas, autoresolution_count_pix_toa_phoa_snr); if (!P) return NULL; /* Determine the lateral HEALPix resolution. */ nside = npix2nside(*npix); /* Zero all pixels that didn't meet the TDOA cut. */ for (i = maxpix; i < *npix; i ++) { long ipix = gsl_permutation_get(pix_perm, i); P[ipix] = -INFINITY; } /* Use our own error handler while in parallel section to avoid concurrent * calls to the GSL error handler, which if provided by the user may not * be threadsafe. */ old_handler = gsl_set_error_handler(my_gsl_error); /* Compute posterior factor for amplitude consistency. */ #pragma omp parallel for firstprivate(gsl_errno) lastprivate(gsl_errno) for (i = 0; i < maxpix; i ++) { /* Cancel further computation if a GSL error condition has occurred. * * Note: if one thread sets gsl_errno, not necessarily all thread will * get the updated value. That's OK, because most failure modes will * cause GSL error conditions on all threads. If we cared to have any * failure on any thread terminate all of the other threads as quickly * as possible, then we would want to insert the following pragma here: * * #pragma omp flush(gsl_errno) * * and likewise before any point where we set gsl_errno. */ if (gsl_errno != GSL_SUCCESS) goto skip; { long ipix = gsl_permutation_get(pix_perm, i); double complex F[nifos]; double theta, phi; int itwopsi, iu, it, iifo; double accum = -INFINITY; double complex exp_i_toaphoa[nifos]; double dtau[nifos], mean_dtau; /* Prepare workspace for adaptive integrator. */ gsl_integration_workspace *workspace = gsl_integration_workspace_alloc(subdivision_limit); /* If the workspace could not be allocated, then record the GSL * error value for later reporting when we leave the parallel * section. Then, skip to the next loop iteration. */ if (!workspace) { gsl_errno = GSL_ENOMEM; goto skip; } /* Look up polar coordinates of this pixel */ pix2ang_ring(nside, ipix, &theta, &phi); toa_errors(dtau, theta, phi, gmst, nifos, locations, toas); for (iifo = 0; iifo < nifos; iifo ++) exp_i_toaphoa[iifo] = exp_i_phoas[iifo] * exp_i(w1s[iifo] * dtau[iifo]); /* Find mean arrival time error */ mean_dtau = gsl_stats_wmean(w_toas, 1, dtau, 1, nifos); /* Look up antenna factors */ for (iifo = 0; iifo < nifos; iifo++) { XLALComputeDetAMResponse( (double *)&F[iifo], /* Type-punned real part */ 1 + (double *)&F[iifo], /* Type-punned imag part */ responses[iifo], phi, M_PI_2 - theta, 0, gmst); F[iifo] *= d1[iifo]; } /* Integrate over 2*psi */ for (itwopsi = 0; itwopsi < ntwopsi; itwopsi++) { const double twopsi = (2 * M_PI / ntwopsi) * itwopsi; const double complex exp_i_twopsi = exp_i(twopsi); /* Integrate over u from u=-1 to u=1. */ for (iu = -nu; iu <= nu; iu++) { const double u = (double)iu / nu; const double u2 = gsl_pow_2(u); double A = 0, B = 0; double breakpoints[5]; int num_breakpoints = 0; double log_offset = -INFINITY; /* The log-likelihood is quadratic in the estimated and true * values of the SNR, and in 1/r. It is of the form A/r^2 + B/r, * where A depends only on the true values of the SNR and is * strictly negative and B depends on both the true values and * the estimates and is strictly positive. * * The middle breakpoint is at the maximum of the log-likelihood, * occurring at 1/r=-B/2A. The lower and upper breakpoints occur * when the likelihood becomes eta times its maximum value. This * occurs when * * A/r^2 + B/r = log(eta) - B^2/4A. * */ /* Perform arrival time integral */ double accum1 = -INFINITY; for (it = -nt/2; it <= nt/2; it++) { const double t = mean_dtau + LAL_REARTH_SI / LAL_C_SI * it / nt; double complex i0arg_complex = 0; for (iifo = 0; iifo < nifos; iifo++) { const double complex tmp = F[iifo] * exp_i_twopsi; /* FIXME: could use - sign here to avoid conj below, but * this probably just sets our sign convention relative to * detection pipeline */ double complex phase_rhotimesr = 0.5 * (1 + u2) * creal(tmp) + I * u * cimag(tmp); const double abs_rhotimesr_2 = cabs2(phase_rhotimesr); const double abs_rhotimesr = sqrt(abs_rhotimesr_2); phase_rhotimesr /= abs_rhotimesr; i0arg_complex += exp_i_toaphoa[iifo] * exp_i(-w1s[iifo] * t) * phase_rhotimesr * gsl_pow_2(snrs[iifo]); } const double i0arg = cabs(i0arg_complex); accum1 = logaddexp(accum1, log(gsl_sf_bessel_I0_scaled(i0arg)) + i0arg - 0.5 * gsl_stats_wtss_m(w_toas, 1, dtau, 1, nifos, t)); } /* Loop over detectors */ for (iifo = 0; iifo < nifos; iifo++) { const double complex tmp = F[iifo] * exp_i_twopsi; /* FIXME: could use - sign here to avoid conj below, but * this probably just sets our sign convention relative to * detection pipeline */ double complex phase_rhotimesr = 0.5 * (1 + u2) * creal(tmp) + I * u * cimag(tmp); const double abs_rhotimesr_2 = cabs2(phase_rhotimesr); const double abs_rhotimesr = sqrt(abs_rhotimesr_2); A += abs_rhotimesr_2; B += abs_rhotimesr * snrs[iifo]; } A *= -0.5; { const double middle_breakpoint = -2 * A / B; const double lower_breakpoint = 1 / (1 / middle_breakpoint + sqrt(log(eta) / A)); const double upper_breakpoint = 1 / (1 / middle_breakpoint - sqrt(log(eta) / A)); breakpoints[num_breakpoints++] = min_distance; if(lower_breakpoint > breakpoints[num_breakpoints-1] && lower_breakpoint < max_distance) breakpoints[num_breakpoints++] = lower_breakpoint; if(middle_breakpoint > breakpoints[num_breakpoints-1] && middle_breakpoint < max_distance) breakpoints[num_breakpoints++] = middle_breakpoint; if(upper_breakpoint > breakpoints[num_breakpoints-1] && upper_breakpoint < max_distance) breakpoints[num_breakpoints++] = upper_breakpoint; breakpoints[num_breakpoints++] = max_distance; } { /* * Set log_offset to the maximum of the logarithm of the * radial integrand evaluated at all of the breakpoints. */ int ibreakpoint; for (ibreakpoint = 0; ibreakpoint < num_breakpoints; ibreakpoint++) { const double new_log_offset = log_radial_integrand( breakpoints[ibreakpoint], A, B, prior_distance_power); if (new_log_offset < INFINITY && new_log_offset > log_offset) log_offset = new_log_offset; } } { /* Perform adaptive integration. Stop when a relative * accuracy of 0.05 has been reached. */ inner_integrand_params integrand_params = {A, B, log_offset, prior_distance_power}; const gsl_function func = {radial_integrand, &integrand_params}; double result, abserr; int ret = gsl_integration_qagp(&func, &breakpoints[0], num_breakpoints, DBL_MIN, 0.05, subdivision_limit, workspace, &result, &abserr); /* If the integrator failed, then record the GSL error * value for later reporting when we leave the parallel * section. Then, break out of the loop. */ if (ret != GSL_SUCCESS) { gsl_errno = ret; gsl_integration_workspace_free(workspace); goto skip; } /* Take the logarithm and put the log-normalization back in. */ result = log(result) + integrand_params.log_offset + accum1; /* Accumulate result. */ accum = logaddexp(accum, result); } } } /* Discard workspace for adaptive integrator. */ gsl_integration_workspace_free(workspace); /* Store log posterior. */ P[ipix] = accum; } skip: /* this statement intentionally left blank */; } /* Restore old error handler. */ gsl_set_error_handler(old_handler); /* Free permutation. */ gsl_permutation_free(pix_perm); /* Check if there was an error in any thread evaluating any pixel. If there * was, raise the error and return. */ if (gsl_errno != GSL_SUCCESS) { free(P); GSL_ERROR_NULL(gsl_strerror(gsl_errno), gsl_errno); } /* Exponentiate and normalize posterior. */ pix_perm = get_pixel_ranks(*npix, P); if (!pix_perm) { free(P); return NULL; } exp_normalize(*npix, P, pix_perm); gsl_permutation_free(pix_perm); return P; }
double bayestar_log_posterior_toa_phoa_snr( double ra, double sin_dec, double distance, double u, double twopsi, double t, double gmst, /* Greenwich mean sidereal time in radians. */ int nifos, /* Input: number of detectors. */ const float (**responses)[3], /* Pointers to detector responses. */ const double **locations, /* Pointers to locations of detectors in Cartesian geographic coordinates. */ const double *toas, /* Input: array of times of arrival with arbitrary relative offset. (Make toas[0] == 0.) */ const double *phoas, /* Input: array of times of arrival with arbitrary relative offset. (Make toas[0] == 0.) */ const double *snrs, /* Input: array of SNRs. */ const double *w_toas, /* Input: sum-of-squares weights, (1/TOA variance)^2. */ const double *w1s, /* Input: first moments of angular frequency. */ const double *w2s, /* Input: second moments of angular frequency. */ const double *horizons, /* Distances at which a source would produce an SNR of 1 in each detector. */ int prior_distance_power) /* Use a prior of (distance)^(prior_distance_power) */ { int iifo; const double dec = asin(sin_dec); const double u2 = gsl_pow_2(u); const double complex exp_i_twopsi = exp_i(twopsi); (void)w2s; /* FIXME: remove unused parameter */ /* Compute time of arrival errors */ double dt[nifos]; toa_errors(dt, M_PI_2 - dec, ra, gmst, nifos, locations, toas); { double mean_dt = gsl_stats_wmean(w_toas, 1, dt, 1, nifos); for (iifo = 0; iifo < nifos; iifo++) dt[iifo] += t - mean_dt; } /* Rescale distances so that furthest horizon distance is 1. */ double d1[nifos]; { const double d1max = gsl_stats_max(horizons, 1, nifos); for (iifo = 0; iifo < nifos; iifo ++) d1[iifo] = horizons[iifo] / d1max; distance /= d1max; } double logp = 0; double complex i0arg_complex = 0; double A = 0; double B = 0; /* Loop over detectors */ for (iifo = 0; iifo < nifos; iifo++) { double complex F; XLALComputeDetAMResponse( (double *)&F, /* Type-punned real part */ 1 + (double *)&F, /* Type-punned imag part */ responses[iifo], ra, dec, 0, gmst); F *= d1[iifo]; const double complex tmp = F * exp_i_twopsi; double complex phase_rhotimesr = 0.5 * (1 + u2) * creal(tmp) + I * u * cimag(tmp); const double abs_rhotimesr_2 = cabs2(phase_rhotimesr); const double abs_rhotimesr = sqrt(abs_rhotimesr_2); phase_rhotimesr /= abs_rhotimesr; i0arg_complex += exp_i(phoas[iifo] + w1s[iifo] * dt[iifo]) * phase_rhotimesr * gsl_pow_2(snrs[iifo]); logp += -0.5 * w_toas[iifo] * gsl_pow_2(dt[iifo]); A += abs_rhotimesr_2; B += abs_rhotimesr * snrs[iifo]; } A *= -0.5; const double i0arg = cabs(i0arg_complex); /* Should be equivalent to, but more accurate than: logp += log(gsl_sf_bessel_I0(i0arg)) */ logp += log(gsl_sf_bessel_I0_scaled(i0arg)) + i0arg; logp += log_radial_integrand(distance, A, B, prior_distance_power); return logp; }
int PSDCalculator::calculatePowerSpectrum( double *input, int inputLen, double *output, int outputLen, bool removeMean, bool interpolateHoles, bool average, int averageLen, bool apodize, ApodizeFunction apodizeFxn, double gaussianSigma, PSDType outputType, double inputSamplingFreq) { if (outputLen != calculateOutputVectorLength(inputLen, average, averageLen)) { Kst::Debug::self()->log(i18n("in PSDCalculator::calculatePowerSpectrum: received output array with wrong length."), Kst::Debug::Error); return -1; } if (outputLen != _prevOutputLen) { delete[] _a; delete[] _w; _awLen = outputLen*2; _prevOutputLen = outputLen; _a = new double[_awLen]; _w = new double[_awLen]; updateWindowFxn(apodizeFxn, gaussianSigma); } if ( (_prevApodizeFxn != apodizeFxn) || (_prevGaussianSigma != gaussianSigma) ) { updateWindowFxn(apodizeFxn, gaussianSigma); } int currentCopyLen, nsamples = 0; int i_samp, i_subset, ioffset; memset(output, 0, sizeof(double)*outputLen); // initialize output. // Mingw build could be 10 times slower (Gaussian apod, mostly 0 then?) //MeasureTime time_in_rfdt("rdft()"); bool done = false; for (i_subset = 0; !done; i_subset++) { ioffset = i_subset*outputLen; //overlapping average => i_subset*outputLen // only zero pad if we really have to. It is better to adjust the last chunk's // overlap. if (ioffset + _awLen*5/4 < inputLen) { currentCopyLen = _awLen; //will copy a complete window. } else if (_awLen<inputLen) { // count the last one from the end. ioffset = inputLen-_awLen - 1; currentCopyLen = _awLen; //will copy a complete window. done = true; } else { currentCopyLen = inputLen - ioffset; //will copy a partial window. memset(&_a[currentCopyLen], 0, sizeof(double)*(_awLen - currentCopyLen)); //zero the leftovers. done = true; } double mean = 0.0; if (removeMean) { for (i_samp = 0; i_samp < currentCopyLen; i_samp++) { mean += input[i_samp + ioffset]; } mean /= (double)currentCopyLen; } // apply the PSD options (removeMean, apodize, etc.) // separate cases for speed- although this shouldn't really matter- the rdft should be the most time consuming step by far for any large data set. if (removeMean && apodize && interpolateHoles) { for (i_samp = 0; i_samp < currentCopyLen; i_samp++) { _a[i_samp] = (Kst::kstInterpolateNoHoles(input, inputLen, i_samp + ioffset, inputLen) - mean)*_w[i_samp]; } } else if (removeMean && apodize) { for (i_samp = 0; i_samp < currentCopyLen; i_samp++) { _a[i_samp] = (input[i_samp + ioffset] - mean)*_w[i_samp]; } } else if (removeMean && interpolateHoles) { for (i_samp = 0; i_samp < currentCopyLen; i_samp++) { _a[i_samp] = Kst::kstInterpolateNoHoles(input, inputLen, i_samp + ioffset, inputLen) - mean; } } else if (apodize && interpolateHoles) { for (i_samp = 0; i_samp < currentCopyLen; i_samp++) { _a[i_samp] = Kst::kstInterpolateNoHoles(input, inputLen, i_samp + ioffset, inputLen)*_w[i_samp]; } } else if (removeMean) { for (i_samp = 0; i_samp < currentCopyLen; i_samp++) { _a[i_samp] = input[i_samp + ioffset] - mean; } } else if (apodize) { for (i_samp = 0; i_samp < currentCopyLen; i_samp++) { _a[i_samp] = input[i_samp + ioffset]*_w[i_samp]; } } else if (interpolateHoles) { for (i_samp = 0; i_samp < currentCopyLen; i_samp++) { _a[i_samp] = Kst::kstInterpolateNoHoles(input, inputLen, i_samp + ioffset, inputLen); } } else { for (i_samp = 0; i_samp < currentCopyLen; i_samp++) { _a[i_samp] = input[i_samp + ioffset]; } } nsamples += currentCopyLen; #if !defined(__QNX__) rdft(_awLen, 1, _a); //real discrete fourier transorm on _a. #else Q_ASSERT(0); // there is a linking problem when not compling with pch. . . #endif output[0] += _a[0] * _a[0]; output[outputLen-1] += _a[1] * _a[1]; for (i_samp = 1; i_samp < outputLen - 1; i_samp++) { output[i_samp] += cabs2(_a[i_samp * 2], _a[i_samp * 2 + 1]); } } // FIXME: NORMALIZATION. /* This normalization doesn't give the same results as the original KstPSD. double frequencyStep = .5*(double)inputSamplingFreq/(double)(outputLen-1); //normalization factors which were left out earlier for speed. // - 2.0 for the negative frequencies which were neglected by the rdft //FIXME: double check. // - /(_awLen*_awLen) for the constant Wss from numerical recipes in C. (ensure that the window function agrees with this.) // - /i_subset to average the powers in all the subsets. double norm = 2.0/(double)_awLen/(double)_awLen/(double)i_subset; */ // original normalization double frequencyStep = 2.0*(double)inputSamplingFreq/(double)nsamples; //OLD value for frequencyStep. double norm = 2.0/(double)nsamples*2.0/(double)nsamples; //OLD value for norm. switch (outputType) { default: case PSDAmplitudeSpectralDensity: // amplitude spectral density (default) [V/Hz^1/2] norm /= frequencyStep; for (i_samp = 0; i_samp < outputLen; i_samp++) { output[i_samp] = sqrt(output[i_samp]*norm); } break; case PSDPowerSpectralDensity: // power spectral density [V^2/Hz] norm /= frequencyStep; for (i_samp = 0; i_samp < outputLen; i_samp++) { output[i_samp] *= norm; } break; case PSDAmplitudeSpectrum: // amplitude spectrum [V] for (i_samp = 0; i_samp < outputLen; i_samp++) { output[i_samp] = sqrt(output[i_samp]*norm); } break; case PSDPowerSpectrum: // power spectrum [V^2] for (i_samp = 0; i_samp < outputLen; i_samp++) { output[i_samp] *= norm; } break; } return 0; }
void KstPSDGenerator::updateNow() { int i_subset, i_samp; int n_subsets; int v_len; int copyLen; QValueVector<double> psd, f; double mean; double nf; bool done; adjustLengths(); v_len = _inputVector->size(); n_subsets = v_len/_PSDLen+1; if (v_len%_PSDLen==0) n_subsets--; // always update when asked _last_n_new = _inputVector->size(); for (i_samp = 0; i_samp < _PSDLen; i_samp++) { (*_powerVector)[i_samp] = 0; (*_frequencyVector)[i_samp] = i_samp*0.5*_Freq/( _PSDLen-1 ); } _frequencyVectorStep = 0.5*_Freq/(_PSDLen - 1); nf = 0; done = false; for (i_subset = 0; !done; i_subset++) { // copy each chunk into a[] and find mean if (i_subset*_PSDLen + _ALen < v_len) { copyLen = _ALen; } else { copyLen = v_len - i_subset*_PSDLen; done = true; } mean = 0; for (i_samp = 0; i_samp < copyLen; i_samp++) { mean += ( _a[i_samp] = _inputVector->at(i_samp + i_subset*_PSDLen) ); } if (copyLen > 1) { mean /= (double)copyLen; } if (apodize()) { GenW(copyLen); } // remove mean and apodize if (removeMean() && apodize()) { for (i_samp=0; i_samp<copyLen; i_samp++) { _a[i_samp]= (_a[i_samp]-mean)*_w[i_samp]; } } else if (removeMean()) { for (i_samp=0; i_samp<copyLen; i_samp++) { _a[i_samp] -= mean; } } else if (apodize()) { for (i_samp=0; i_samp<copyLen; i_samp++) { _a[i_samp] *= _w[i_samp]; } } nf += copyLen; for (;i_samp < _ALen; i_samp++) { _a[i_samp] = 0.0; } // fft a rdft(_ALen, 1, _a); (*_powerVector)[0] += _a[0]*_a[0]; (*_powerVector)[_PSDLen-1] += _a[1]*_a[1]; for (i_samp=1; i_samp<_PSDLen-1; i_samp++) { (*_powerVector)[i_samp]+= cabs2(_a[i_samp*2], _a[i_samp*2+1]); } } _last_f0 = 0; _last_n_subsets = n_subsets; _last_n_new = 0; nf = 1.0/(double(_Freq)*double(nf/2.0)); for ( i_samp = 0; i_samp<_PSDLen; i_samp++ ) { (*_powerVector)[i_samp] = sqrt((*_powerVector)[i_samp]*nf); } if (_Freq <= 0.0) { _Freq = 1.0; } }