def __call__(self, tseries): """ Transform the real-valued time series stored in tseries into a complex-valued time series. The return value is a newly-allocated complex time series. The input time series is stored in the real part of the output time series, and the complex part stores the quadrature phase. """ # # transform to frequency series # lal.REAL8TimeFreqFFT(self.in_fseries, tseries, self.fwdplan) # # transform to complex time series # tseries = lal.CreateCOMPLEX16TimeSeries(length=self.n) lal.COMPLEX16FreqTimeFFT( tseries, self.add_quadrature_phase(self.in_fseries, self.n), self.revplan) # # done # return tseries
def matched_filter_spa(template, psd): """Create a complex matched filter kernel from a stationary phase approximation template and a PSD.""" fdfilter = matched_filter_real_fd(template, psd) fdfilter2 = add_quadrature_phase(fdfilter) tdfilter = lal.CreateCOMPLEX16TimeSeries(None, lal.LIGOTimeGPS(0), 0, 0, lal.DimensionlessUnit, len(fdfilter2.data.data)) plan = CreateReverseCOMPLEX16FFTPlan(len(fdfilter2.data.data), 0) lal.COMPLEX16FreqTimeFFT(tdfilter, fdfilter2, plan) return tdfilter
def DataInverseFourier( hf ): # Complex fft wrapper (COMPLEX16Freq ->COMPLEX16Time. No error checking or padding! FDlen = hf.data.length dt = 1. / hf.deltaF / FDlen revplan = lal.CreateReverseCOMPLEX16FFTPlan(FDlen, 0) ht = lal.CreateCOMPLEX16TimeSeries("Template h(t)", hf.epoch, hf.f0, dt, lal.lalDimensionlessUnit, FDlen) lal.COMPLEX16FreqTimeFFT(ht, hf, revplan) # assume memory freed by swig python return ht
def normalized_autocorrelation(fseries, revplan): data = fseries.data.data fseries = lal.CreateCOMPLEX16FrequencySeries( name=fseries.name, epoch=fseries.epoch, f0=fseries.f0, deltaF=fseries.deltaF, sampleUnits=fseries.sampleUnits, length=len(data)) fseries.data.data = data * numpy.conj(data) tseries = lal.CreateCOMPLEX16TimeSeries(name="timeseries", epoch=fseries.epoch, f0=fseries.f0, deltaT=1. / (len(data) * fseries.deltaF), length=len(data), sampleUnits=lal.DimensionlessUnit) tseries.data.data = numpy.empty((len(data), ), dtype="cdouble") lal.COMPLEX16FreqTimeFFT(tseries, fseries, revplan) data = tseries.data.data tseries.data.data = data / data[0] return tseries
print(det, " rho = ", rhoDet) print("Network : ", np.sqrt(rho2Net)) if opts.plot_ShowH: print( " == Plotting *raw* detector data data (time domain) via MANUAL INVERSE FFT == " ) print(" [This plot includes any windowing and data padding] ") for det in detectors: revplan = lal.CreateReverseCOMPLEX16FFTPlan( len(data_dict[det].data.data), 0) ht = lal.CreateCOMPLEX16TimeSeries("ht", lal.LIGOTimeGPS(0.), 0., Psig.deltaT, lal.lalDimensionlessUnit, len(data_dict[det].data.data)) lal.COMPLEX16FreqTimeFFT(ht, data_dict[det], revplan) tvals = float(ht.epoch - theEpochFiducial) + ht.deltaT * np.arange( len(ht.data.data)) # Not correct timing relative to zero - FIXME plt.figure(1) plt.plot(tvals, np.abs(ht.data.data), label=det) plt.legend() plt.show() print( " == Plotting detector data (time domain; requires regeneration, MANUAL TIMESHIFTS, and seperate code path! Argh!) == " ) P = Psig.copy() P.tref = Psig.tref for det in detectors: P.detector = det
def make_whitened_template(self, template_table_row): # FIXME: This is won't work #assert template_table_row in self.template_table, "The input Sngl_Inspiral:Table is not found in the workspace." # Create template fseries = generate_template(template_table_row, self.approximant, self.sample_rate_max, self.working_duration, self.f_low, self.fhigh, fwdplan=self.fwdplan, fworkspace=self.fworkspace) if FIR_WHITENER: # # Compute a product of freq series of the whitening kernel and the template (convolution in time domain) then add quadrature phase # assert (len(self.kernel_fseries.data.data) // 2 + 1) == len( fseries.data.data ), "the size of whitening kernel freq series does not match with a given format of COMPLEX16FrequencySeries." fseries.data.data *= self.kernel_fseries.data.data[ len(self.kernel_fseries.data.data) // 2 - 1:] fseries = templates.QuadraturePhase.add_quadrature_phase( fseries, self.working_length) else: # # whiten and add quadrature phase ("sine" component) # if self.psd is not None: lal.WhitenCOMPLEX16FrequencySeries(fseries, self.psd) fseries = templates.QuadraturePhase.add_quadrature_phase( fseries, self.working_length) # # compute time-domain autocorrelation function # if self.autocorrelation_length is not None: autocorrelation = templates.normalized_autocorrelation( fseries, self.revplan).data.data else: autocorrelation = None # # transform template to time domain # lal.COMPLEX16FreqTimeFFT(self.tseries, fseries, self.revplan) data = self.tseries.data.data epoch_time = fseries.epoch.gpsSeconds + fseries.epoch.gpsNanoSeconds * 1.e-9 # # extract the portion to be used for filtering # # # condition the template if necessary (e.g. line up IMR # waveforms by peak amplitude) # if self.approximant in templates.gstlal_IMR_approximants: data, target_index = condition_imr_template( self.approximant, data, epoch_time, self.sample_rate_max, self.max_ringtime) # record the new end times for the waveforms (since we performed the shifts) template_table_row.end = LIGOTimeGPS( float(target_index - (len(data) - 1.)) / self.sample_rate_max) else: if self.sample_rate_max > self.fhigh * 2.: data, target_index = condition_ear_warn_template( self.approximant, data, epoch_time, self.sample_rate_max, self.max_shift_time) data *= tukeywindow(data, samps=32) # record the new end times for the waveforms (since we performed the shifts) template_table_row.end = LIGOTimeGPS( float(target_index) / self.sample_rate_max) else: data *= tukeywindow(data, samps=32) data = data[-self.length_max:] # # normalize so that inner product of template with itself # is 2 # norm = abs(numpy.dot(data, numpy.conj(data))) data *= cmath.sqrt(2 / norm) # # sigmasq = 2 \sum_{k=0}^{N-1} |\tilde{h}_{k}|^2 / S_{k} \Delta f # # XLALWhitenCOMPLEX16FrequencySeries() computed # # \tilde{h}'_{k} = \sqrt{2 \Delta f} \tilde{h}_{k} / \sqrt{S_{k}} # # and XLALCOMPLEX16FreqTimeFFT() computed # # h'_{j} = \Delta f \sum_{k=0}^{N-1} exp(2\pi i j k / N) \tilde{h}'_{k} # # therefore, "norm" is # # \sum_{j} |h'_{j}|^{2} = (\Delta f)^{2} \sum_{j} \sum_{k=0}^{N-1} \sum_{k'=0}^{N-1} exp(2\pi i j (k-k') / N) \tilde{h}'_{k} \tilde{h}'^{*}_{k'} # = (\Delta f)^{2} \sum_{k=0}^{N-1} \sum_{k'=0}^{N-1} \tilde{h}'_{k} \tilde{h}'^{*}_{k'} \sum_{j} exp(2\pi i j (k-k') / N) # = (\Delta f)^{2} N \sum_{k=0}^{N-1} |\tilde{h}'_{k}|^{2} # = (\Delta f)^{2} N 2 \Delta f \sum_{k=0}^{N-1} |\tilde{h}_{k}|^{2} / S_{k} # = (\Delta f)^{2} N sigmasq # # and \Delta f = 1 / (N \Delta t), so "norm" is # # \sum_{j} |h'_{j}|^{2} = 1 / (N \Delta t^2) sigmasq # # therefore # # sigmasq = norm * N * (\Delta t)^2 # sigmasq = norm * len(data) / self.sample_rate_max**2. return data, autocorrelation, sigmasq