/** * Window and IFFT a FD waveform to TD, then window in TD. * Requires that the FD waveform be generated outside of f_min and f_max. * FD waveform is modified. */ static int FDToTD(REAL8TimeSeries **signalTD, const COMPLEX16FrequencySeries *signalFD, const REAL8 totalMass, const REAL8 deltaT, const REAL8 f_min, const REAL8 f_max, const REAL8 f_min_wide, const REAL8 f_max_wide) { const LIGOTimeGPS gpstime_zero = {0, 0}; const size_t nf = signalFD->data->length; const size_t nt = 2 * (nf - 1); /* Calculate the expected lengths of the FD and TD vectors from the * deltaF and deltaT passed in to this function */ //const size_t exp_nt = (size_t) 1. / (signalFD->deltaF * deltaT); //const size_t exp_nf = (exp_nt / 2) + 1; const REAL8 windowLength = 20. * totalMass * LAL_MTSUN_SI / deltaT; const REAL8 winFLo = 0.2*f_min_wide + 0.8*f_min; /* frequency used for tapering, slightly less than f_min to minimize FFT artifacts * equivalent to winFLo = f_min_wide + 0.8*(f_min - f_min_wide) */ REAL8 winFHi = f_max_wide; COMPLEX16 *FDdata = signalFD->data->data; REAL8FFTPlan *revPlan; REAL8 *TDdata; size_t k; /* check inputs */ if (f_min_wide >= f_min) XLAL_ERROR(XLAL_EDOM); /* apply the softening window function */ if (winFHi > 0.5 / deltaT) winFHi = 0.5 / deltaT; for (k = nf;k--;) { const REAL8 f = k / (deltaT * nt); REAL8 softWin = PlanckTaper(f, f_min_wide, winFLo) * (1.0 - PlanckTaper(f, f_max, winFHi)); FDdata[k] *= softWin; } /* allocate output */ *signalTD = XLALCreateREAL8TimeSeries("h", &gpstime_zero, 0.0, deltaT, &lalStrainUnit, nt); /* Inverse Fourier transform */ revPlan = XLALCreateReverseREAL8FFTPlan(nt, 1); if (!revPlan) { XLALDestroyREAL8TimeSeries(*signalTD); *signalTD = NULL; XLAL_ERROR(XLAL_EFUNC); } XLALREAL8FreqTimeFFT(*signalTD, signalFD, revPlan); XLALDestroyREAL8FFTPlan(revPlan); if (!(*signalTD)) XLAL_ERROR(XLAL_EFUNC); /* apply a linearly decreasing window at the end * of the waveform in order to avoid edge effects. */ if (windowLength > (*signalTD)->data->length) XLAL_ERROR(XLAL_ERANGE); TDdata = (*signalTD)->data->data; for (k = windowLength; k--;) TDdata[nt-k-1] *= k / windowLength; return XLAL_SUCCESS; }
static PyObject *pylal_XLALREAL8FreqTimeFFT(PyObject *self, PyObject *args) { pylal_REAL8TimeSeries *tser; pylal_COMPLEX16FrequencySeries *fser; pylal_REAL8FFTPlan *plan; if(!PyArg_ParseTuple(args, "O!O!O!", &pylal_REAL8TimeSeries_Type, &tser, &pylal_COMPLEX16FrequencySeries_Type, &fser, &pylal_REAL8FFTPlan_Type, &plan)) return NULL; if(XLALREAL8FreqTimeFFT(tser->series, fser->series, plan->plan)) { pylal_set_exception_from_xlalerrno(); return NULL; } Py_INCREF(Py_None); return Py_None; }
/* creates a waveform in the time domain; the waveform might be generated in * the frequency-domain and transformed */ int create_td_waveform(REAL8TimeSeries ** h_plus, REAL8TimeSeries ** h_cross, struct params p) { clock_t timer_start = 0; if (p.condition) { if (p.verbose) { fprintf(stderr, "generating waveform in time domain using XLALSimInspiralTD...\n"); timer_start = clock(); } XLALSimInspiralTD(h_plus, h_cross, p.m1, p.m2, p.s1x, p.s1y, p.s1z, p.s2x, p.s2y, p.s2z, p.distance, p.inclination, p.phiRef, p.longAscNodes, p.eccentricity, p.meanPerAno, 1.0 / p.srate, p.f_min, p.fRef, p.params, p.approx); if (p.verbose) fprintf(stderr, "generation took %g seconds\n", (double)(clock() - timer_start) / CLOCKS_PER_SEC); } else if (p.domain == LAL_SIM_DOMAIN_TIME) { /* generate time domain waveform */ if (p.verbose) { fprintf(stderr, "generating waveform in time domain using XLALSimInspiralChooseTDWaveform...\n"); timer_start = clock(); } XLALSimInspiralChooseTDWaveform(h_plus, h_cross, p.m1, p.m2, p.s1x, p.s1y, p.s1z, p.s2x, p.s2y, p.s2z, p.distance, p.inclination, p.phiRef, p.longAscNodes, p.eccentricity, p.meanPerAno, 1.0 / p.srate, p.f_min, p.fRef, p.params, p.approx); if (p.verbose) fprintf(stderr, "generation took %g seconds\n", (double)(clock() - timer_start) / CLOCKS_PER_SEC); } else { COMPLEX16FrequencySeries *htilde_plus = NULL; COMPLEX16FrequencySeries *htilde_cross = NULL; REAL8FFTPlan *plan; double chirplen, deltaF; int chirplen_exp; /* determine required frequency resolution */ /* length of the chirp in samples */ chirplen = imr_time_bound(p.f_min, p.m1, p.m2, p.s1z, p.s2z) * p.srate; /* make chirplen next power of two */ frexp(chirplen, &chirplen_exp); chirplen = ldexp(1.0, chirplen_exp); deltaF = p.srate / chirplen; if (p.verbose) fprintf(stderr, "using frequency resolution deltaF = %g Hz\n", deltaF); /* generate waveform in frequency domain */ if (p.verbose) { fprintf(stderr, "generating waveform in frequency domain using XLALSimInspiralChooseFDWaveform...\n"); timer_start = clock(); } XLALSimInspiralChooseFDWaveform(&htilde_plus, &htilde_cross, p.m1, p.m2, p.s1x, p.s1y, p.s1z, p.s2x, p.s2y, p.s2z, p.distance, p.inclination, p.phiRef, p.longAscNodes, p.eccentricity, p.meanPerAno, deltaF, p.f_min, 0.5 * p.srate, p.fRef, p.params, p.approx); if (p.verbose) fprintf(stderr, "generation took %g seconds\n", (double)(clock() - timer_start) / CLOCKS_PER_SEC); /* put the waveform in the time domain */ if (p.verbose) { fprintf(stderr, "transforming waveform to time domain...\n"); timer_start = clock(); } *h_plus = XLALCreateREAL8TimeSeries("h_plus", &htilde_plus->epoch, 0.0, 1.0 / p.srate, &lalStrainUnit, (size_t) chirplen); *h_cross = XLALCreateREAL8TimeSeries("h_cross", &htilde_cross->epoch, 0.0, 1.0 / p.srate, &lalStrainUnit, (size_t) chirplen); plan = XLALCreateReverseREAL8FFTPlan((size_t) chirplen, 0); XLALREAL8FreqTimeFFT(*h_cross, htilde_cross, plan); XLALREAL8FreqTimeFFT(*h_plus, htilde_plus, plan); if (p.verbose) fprintf(stderr, "transformation took %g seconds\n", (double)(clock() - timer_start) / CLOCKS_PER_SEC); /* clean up */ XLALDestroyREAL8FFTPlan(plan); XLALDestroyCOMPLEX16FrequencySeries(htilde_cross); XLALDestroyCOMPLEX16FrequencySeries(htilde_plus); } return 0; }