예제 #1
0
    def lal(self):
        """ Returns a LAL Object that contains this data """

        lal_data = None
        if type(self._data) is not _numpy.ndarray:
            raise TypeError("Cannot return lal type from the GPU")
        elif self._data.dtype == _numpy.float32:
            lal_data = _lal.CreateREAL4FrequencySeries("", self._epoch, 0,
                                                       self.delta_f,
                                                       _lal.lalSecondUnit,
                                                       len(self))
        elif self._data.dtype == _numpy.float64:
            lal_data = _lal.CreateREAL8FrequencySeries("", self._epoch, 0,
                                                       self.delta_f,
                                                       _lal.lalSecondUnit,
                                                       len(self))
        elif self._data.dtype == _numpy.complex64:
            lal_data = _lal.CreateCOMPLEX8FrequencySeries(
                "", self._epoch, 0, self.delta_f, _lal.lalSecondUnit,
                len(self))
        elif self._data.dtype == _numpy.complex128:
            lal_data = _lal.CreateCOMPLEX16FrequencySeries(
                "", self._epoch, 0, self.delta_f, _lal.lalSecondUnit,
                len(self))

        lal_data.data.data[:] = self._data

        return lal_data
예제 #2
0
    def lal(self):
        """Produces a LAL frequency series object equivalent to self.

        Returns
        -------
        lal_data : {lal.*FrequencySeries}
            LAL frequency series object containing the same data as self.
            The actual type depends on the sample's dtype. If the epoch of
            self was 'None', the epoch of the returned LAL object will be
            LIGOTimeGPS(0,0); otherwise, the same as that of self.

        Raises
        ------
        TypeError
            If frequency series is stored in GPU memory.
        """

        lal_data = None
        if self._epoch is None:
            ep = _lal.LIGOTimeGPS(0,0)
        else:
            ep = self._epoch

        if self._data.dtype == _numpy.float32:
            lal_data = _lal.CreateREAL4FrequencySeries("",ep,0,self.delta_f,_lal.SecondUnit,len(self))
        elif self._data.dtype == _numpy.float64:
            lal_data = _lal.CreateREAL8FrequencySeries("",ep,0,self.delta_f,_lal.SecondUnit,len(self))
        elif self._data.dtype == _numpy.complex64:
            lal_data = _lal.CreateCOMPLEX8FrequencySeries("",ep,0,self.delta_f,_lal.SecondUnit,len(self))
        elif self._data.dtype == _numpy.complex128:
            lal_data = _lal.CreateCOMPLEX16FrequencySeries("",ep,0,self.delta_f,_lal.SecondUnit,len(self))

        lal_data.data.data[:] = self.numpy()

        return lal_data
예제 #3
0
 def non_herm_hoff(self):
     """
     Returns the 2-sided h(f) associated with the real-valued h(t) seen in a real instrument.
     Translates epoch as needed.
     Based on 'non_herm_hoff' in lalsimutils.py
     """
     htR = self.real_hoft(
     )  # Generate real-valued TD waveform, including detector response
     if self.P.deltaF == None:  # h(t) was not zero-padded, so do it now
         TDlen = nextPow2(htR.data.length)
         htR = lal.ResizeREAL8TimeSeries(htR, 0, TDlen)
     else:  # Check zero-padding was done to expected length
         TDlen = int(1. / self.P.deltaF * 1. / self.P.deltaT)
         assert TDlen == htR.data.length
     fwdplan = lal.CreateForwardCOMPLEX16FFTPlan(htR.data.length, 0)
     htC = lal.CreateCOMPLEX16TimeSeries("hoft", htR.epoch, htR.f0,
                                         htR.deltaT, htR.sampleUnits,
                                         htR.data.length)
     # copy h(t) into a COMPLEX16 array which happens to be purely real
     htC.data.data[:htR.data.length] = htR.data.data
     #        for i in range(htR.data.length):
     #            htC.data.data[i] = htR.data.data[i]
     hf = lal.CreateCOMPLEX16FrequencySeries(
         "Template h(f)", htR.epoch, htR.f0,
         1. / htR.deltaT / htR.data.length, lalsimutils.lsu_HertzUnit,
         htR.data.length)
     lal.COMPLEX16TimeFreqFFT(hf, htC, fwdplan)
     return hf
예제 #4
0
    def _compute_waveform(self, df, f_final):
        """
        Since EOBNRv2 is a time domain waveform, we have to generate it,
        then FFT to frequency domain.
        """
        # need to compute dt from df, duration
        sample_rate = 2**np.ceil(np.log2(2 * f_final))
        dt = 1. / sample_rate
        # get hplus
        hplus, hcross = lalsim.SimIMREOBNRv2DominantMode(
            0., dt, self.m1 * MSUN_SI, self.m2 * MSUN_SI, self.bank.flow,
            1e6 * PC_SI, 0.)
        # zero-pad up to 1/df
        N = int(sample_rate / df)
        hplus = lal.ResizeREAL8TimeSeries(hplus, 0, N)
        # taper
        lalsim.SimInspiralREAL8WaveTaper(hplus.data,
                                         lalsim.SIM_INSPIRAL_TAPER_START)

        # create vector to hold output and plan
        htilde = lal.CreateCOMPLEX16FrequencySeries("h(f)", hplus.epoch,
                                                    hplus.f0, df,
                                                    lal.HertzUnit,
                                                    int(N / 2 + 1))
        fftplan = lal.CreateForwardREAL8FFTPlan(N, 0)

        # do the fft
        lal.REAL8TimeFreqFFT(htilde, hplus, fftplan)

        return htilde
예제 #5
0
def matched_filter_real_fd(template, psd):
    fdfilter = lal.CreateCOMPLEX16FrequencySeries(template.name, template.epoch,
        template.f0, template.deltaF, template.sampleUnits, len(template.data.data))
    fdfilter.data.data = template.data.data
    fdfilter = lal.WhitenCOMPLEX16FrequencySeries(fdfilter, psd)
    fdfilter.data.data /= np.sqrt(np.sum(np.abs(fdfilter.data.data)**2))
    fdfilter = lal.WhitenCOMPLEX16FrequencySeries(fdfilter, psd)
    return fdfilter
예제 #6
0
def add_quadrature_phase(rseries):
    rseries_len = len(rseries.data.data)
    cseries = lal.CreateCOMPLEX16FrequencySeries(rseries.name, rseries.epoch,
        rseries.f0 - rseries.deltaF * (rseries_len - 1), rseries.deltaF,
        rseries.sampleUnits, 2 * (rseries_len - 1))
    cseries.data.data[:rseries_len] = 0
    cseries.data.data[rseries_len:] = 2 * rseries.data.data[1:-1]
    return cseries
예제 #7
0
def generate_template(mass1, mass2, S, f_low, sample_rate, template_duration,
                      approximant, amplitude_order, phase_order):
    template_length = sample_rate * template_duration
    if approximant == lalsimulation.TaylorF2:
        zf, _ = lalsimulation.SimInspiralChooseFDWaveform(
            0, 1 / template_duration, mass1 * lal.LAL_MSUN_SI,
            mass2 * lal.LAL_MSUN_SI, 0, 0, 0, 0, 0, 0, f_low, 0,
            1e6 * lal.LAL_PC_SI, 0, 0, 0, None, None, amplitude_order,
            phase_order, approximant)
        lal.ResizeCOMPLEX16FrequencySeries(zf, 0, template_length // 2 + 1)

        # Generate over-whitened template
        psd = lal.CreateREAL8FrequencySeries(None, zf.epoch, zf.f0, zf.deltaF,
                                             lal.lalDimensionlessUnit,
                                             len(zf.data.data))
        psd.data.data = S(abscissa(psd))
        zW = matched_filter_spa(zf, psd)
    elif approximant == lalsimulation.TaylorT4:
        hplus, hcross = lalsimulation.SimInspiralChooseTDWaveform(
            0, 1 / sample_rate, mass1 * lal.LAL_MSUN_SI,
            mass2 * lal.LAL_MSUN_SI, 0, 0, 0, 0, 0, 0, f_low, f_low,
            1e6 * lal.LAL_PC_SI, 0, 0, 0, None, None, amplitude_order,
            phase_order, approximant)

        ht = lal.CreateREAL8TimeSeries(None,
                                       lal.LIGOTimeGPS(-template_duration),
                                       hplus.f0, hplus.deltaT,
                                       hplus.sampleUnits, template_length)
        hf = lal.CreateCOMPLEX16FrequencySeries(None, lal.LIGOTimeGPS(0), 0, 0,
                                                lal.lalDimensionlessUnit,
                                                template_length // 2 + 1)
        plan = CreateForwardREAL8FFTPlan(template_length, 0)

        ht.data.data[:-len(hplus.data.data)] = 0
        ht.data.data[-len(hplus.data.data):] = hplus.data.data
        lal.REAL8TimeFreqFFT(hf, ht, plan)

        psd = lal.CreateREAL8FrequencySeries(None, hf.epoch, hf.f0, hf.deltaF,
                                             lal.lalDimensionlessUnit,
                                             len(hf.data.data))
        psd.data.data = S(abscissa(psd))

        zWreal = matched_filter_real(hf, psd)

        ht.data.data[:-len(hcross.data.data)] = 0
        ht.data.data[-len(hcross.data.data):] = hcross.data.data

        lal.REAL8TimeFreqFFT(hf, ht, plan)
        zWimag = matched_filter_real(hf, psd)

        zW = lal.CreateCOMPLEX16TimeSeries(None, zWreal.epoch, zWreal.f0,
                                           zWreal.deltaT, zWreal.sampleUnits,
                                           len(zWreal.data.data))
        zW.data.data = zWreal.data.data + zWimag.data.data * 1j
    else:
        raise ValueError("unrecognized approximant")
    return zW.data.data[::-1].conj() * np.sqrt(
        2) * template_duration / sample_rate / 2
예제 #8
0
def create_FIR_whitener_kernel(length, duration, sample_rate, psd):
    assert psd
    #
    # Add another COMPLEX16TimeSeries and COMPLEX16FrequencySeries for kernel's FFT (Leo)
    #

    # Add another FFT plan for kernel FFT (Leo)
    fwdplan_kernel = lal.CreateForwardCOMPLEX16FFTPlan(length, 1)
    kernel_tseries = lal.CreateCOMPLEX16TimeSeries(
        name="timeseries of whitening kernel",
        epoch=LIGOTimeGPS(0.),
        f0=0.,
        deltaT=1.0 / sample_rate,
        length=length,
        sampleUnits=lal.Unit("strain"))
    kernel_fseries = lal.CreateCOMPLEX16FrequencySeries(
        name="freqseries of whitening kernel",
        epoch=LIGOTimeGPS(0),
        f0=0.0,
        deltaF=1.0 / duration,
        length=length,
        sampleUnits=lal.Unit("strain s"))

    #
    # Obtain a kernel of zero-latency whitening filter and
    # adjust its length (Leo)
    #

    psd_fir_kernel = reference_psd.PSDFirKernel()
    (kernel, latency,
     fir_rate) = psd_fir_kernel.psd_to_linear_phase_whitening_fir_kernel(
         psd, nyquist=sample_rate / 2.0)
    (
        kernel, theta
    ) = psd_fir_kernel.linear_phase_fir_kernel_to_minimum_phase_whitening_fir_kernel(
        kernel, fir_rate)
    kernel = kernel[-1::-1]
    # FIXME this is off by one sample, but shouldn't be. Look at the miminum phase function
    # assert len(kernel) == length
    if len(kernel) < length:
        kernel = numpy.append(kernel, numpy.zeros(length - len(kernel)))
    else:
        kernel = kernel[:length]

    kernel_tseries.data.data = kernel

    #
    # FFT of the kernel
    #

    lal.COMPLEX16TimeFreqFFT(kernel_fseries, kernel_tseries,
                             fwdplan_kernel)  #FIXME

    return kernel_fseries
예제 #9
0
 def complex_hoff(self, force_T=False):
     htC = self.complex_hoft(force_T=force_T, deltaT=self.P.deltaT)
     TDlen = int(1. / self.P.deltaF * 1. / self.P.deltaT)
     assert TDlen == htC.data.length
     hf = lal.CreateCOMPLEX16FrequencySeries(
         "Template h(f)", htC.epoch, htC.f0,
         1. / htC.deltaT / htC.data.length, lalsimutils.lsu_HertzUnit,
         htC.data.length)
     fwdplan = lal.CreateForwardCOMPLEX16FFTPlan(htC.data.length, 0)
     lal.COMPLEX16TimeFreqFFT(hf, htC, fwdplan)
     return hf
def DataFourier(
    ht
):  # Complex fft wrapper (COMPLEX16Time ->COMPLEX16Freq. No error checking or padding!
    TDlen = ht.data.length
    fwdplan = lal.CreateForwardCOMPLEX16FFTPlan(TDlen, 0)
    hf = lal.CreateCOMPLEX16FrequencySeries("Template h(f)", ht.epoch, ht.f0,
                                            1. / ht.deltaT / TDlen,
                                            lal.lalHertzUnit, TDlen)
    lal.COMPLEX16TimeFreqFFT(hf, ht, fwdplan)
    # assume memory freed by swig python
    return hf
예제 #11
0
def init_ifoData(ifoData):

    ifoData.modelDomain = lalsimulation.LAL_SIM_DOMAIN_FREQUENCY

    id = ifoData
    while id is not None:
        # Set the model domain to the frequency domain
        id.modelDomain = lalsimulation.LAL_SIM_DOMAIN_FREQUENCY

        # Create some vectors to store the waveforms in
        freqData = id.freqData
        id.freqModelhPlus = lal.CreateCOMPLEX16FrequencySeries(
            "freqModelhPlus", freqData.epoch, freqData.f0, freqData.deltaF,
            freqData.sampleUnits, freqData.data.length)
        id.freqModelhCross = lal.CreateCOMPLEX16FrequencySeries(
            "freqModelhCross", freqData.epoch, freqData.f0, freqData.deltaF,
            freqData.sampleUnits, freqData.data.length)

        #Initialise the lalinference variables on the ifoData
        id.modelParams = li.Variables()
        id = id.next
예제 #12
0
    def to_lal_frequencyseries(self):
        """
        Output the frequency series strain data as a LAL FrequencySeries object.
        """

        laldata = lal.CreateCOMPLEX16FrequencySeries(
            "", lal.LIGOTimeGPS(self.start_time), self.frequency_array[0],
            (self.frequency_array[1] - self.frequency_array[0]),
            lal.SecondUnit, len(self.frequency_domain_strain))
        laldata.data.data[:] = self.frequency_domain_strain

        return laldata
예제 #13
0
def prepare_fseries_for_complex16tseries(series):
    """
	Construct a COMPLEX16FrequencySeries object suitable for storing
	the Fourier transform of a COMPLEX16TimeSeries object.
	"""
    n = len(series.data.data)
    return lal.CreateCOMPLEX16FrequencySeries(
        name=series.name,
        epoch=series.epoch,
        f0=series.f0,  # note: non-zero f0 not supported by LAL
        deltaF=1.0 / (n * series.deltaT),
        sampleUnits=series.sampleUnits * lal.SecondUnit,
        length=n)
예제 #14
0
    def __init__(self, mass1, mass2, S, f_low, approximant, amplitude_order,
                 phase_order):
        """Create a TaylorF2 signal model with the given masses, PSD function
        S(f), PN amplitude order, and low-frequency cutoff."""

        if approximant == lalsimulation.TaylorF2:
            # Frequency-domain post-Newtonian inspiral waveform.
            h, _ = lalsimulation.SimInspiralChooseFDWaveform(
                0, 1, mass1 * lal.LAL_MSUN_SI, mass2 * lal.LAL_MSUN_SI, 0, 0,
                0, 0, 0, 0, f_low, 0, 1e6 * lal.LAL_PC_SI, 0, 0, 0, None, None,
                amplitude_order, 0, approximant)

            # Find indices of first and last nonzero samples.
            nonzero = np.nonzero(h.data.data)[0]
            first_nonzero = nonzero[0]
            last_nonzero = nonzero[-1]
        elif approximant == lalsimulation.TaylorT4:
            # Time-domain post-Newtonian inspiral waveform.
            hplus, hcross = lalsimulation.SimInspiralChooseTDWaveform(
                0, 1 / 4096, mass1 * lal.LAL_MSUN_SI, mass2 * lal.LAL_MSUN_SI,
                0, 0, 0, 0, 0, 0, f_low, f_low, 1e6 * lal.LAL_PC_SI, 0, 0, 0,
                None, None, amplitude_order, phase_order, approximant)

            hplus.data.data += hcross.data.data
            hplus.data.data /= np.sqrt(2)

            h = lal.CreateCOMPLEX16FrequencySeries(
                None, lal.LIGOTimeGPS(0), 0, 0, lal.lalDimensionlessUnit,
                len(hplus.data.data) // 2 + 1)
            plan = CreateForwardREAL8FFTPlan(len(hplus.data.data), 0)
            lal.REAL8TimeFreqFFT(h, hplus, plan)

            f = h.f0 + len(h.data.data) * h.deltaF
            first_nonzero = long(np.floor((f_low - h.f0) / h.deltaF))
            last_nonzero = long(np.ceil((2048 - h.f0) / h.deltaF))
            last_nonzero = min(last_nonzero, len(h.data.data) - 1)
        else:
            raise ValueError("unrecognized approximant")

        # Frequency sample points
        self.dw = 2 * np.pi * h.deltaF
        f = h.f0 + h.deltaF * np.arange(first_nonzero, last_nonzero + 1)
        self.w = 2 * np.pi * f

        # Throw away leading and trailing zeros.
        h = h.data.data[first_nonzero:last_nonzero + 1]

        self.denom_integrand = 4 / (2 * np.pi) * (np.square(h.real) +
                                                  np.square(h.imag)) / S(f)
        self.den = np.trapz(self.denom_integrand, dx=self.dw)
예제 #15
0
    def _compute_waveform(self, df, f_final):
        # Time domain, so compute then FFT
        # need to compute dt from df, duration
        sample_rate = 2**np.ceil(np.log2(2 * f_final))
        dt = 1. / sample_rate
        # Generate waveform in time domain
        hplus, hcross = lalsim.SimInspiralSpinTaylorT5(
            0,  # GW phase at reference freq (rad)
            dt,  # sampling interval (s)
            self.m1 * lal.MSUN_SI,  # mass of companion 1 (kg)
            self.m2 * lal.MSUN_SI,  # mass of companion 2 (kg)
            self.bank.flow,  # start GW frequency (Hz)
            1e6 * PC_SI,  # distance of source (m)
            self.s1x,  # initial value of S1x
            self.s1y,  # initial value of S1y
            self.s1z,  # initial value of S1z
            self.s2x,  # initial value of S2x
            self.s2y,  # initial value of S2y
            self.s2z,  # initial value of S2z
            self.
            inclination,  # inclination angle - careful with definition (line of sight to total vs orbital angular momentum)
            7,  # twice PN phase order
            0)

        # project onto detector
        hoft = project_hplus_hcross(hplus, hcross, self.theta, self.phi,
                                    self.psi)

        # zero-pad up to 1/df
        N = int(sample_rate / df)
        hoft = lal.ResizeREAL8TimeSeries(hoft, 0, N)

        # taper
        lalsim.SimInspiralREAL8WaveTaper(hoft.data,
                                         lalsim.SIM_INSPIRAL_TAPER_STARTEND)

        # create vector to hold output and plan
        htilde = lal.CreateCOMPLEX16FrequencySeries("h(f)", hoft.epoch,
                                                    hoft.f0, df, lal.HertzUnit,
                                                    int(N / 2 + 1))
        fftplan = lal.CreateForwardREAL8FFTPlan(N, 0)

        # do the fft
        lal.REAL8TimeFreqFFT(htilde, hoft, fftplan)

        return htilde
예제 #16
0
    def frequency_series(self, deltaF, detector=None, fwdplan=None):
        """
        Generate a frequency series at a given frequency bin spacing deltaF (Hz) for the waveform using a call to lalsimulation. The function time_series is called first to generate the waveform in the time domain. If detector is None (default), return only hf with no antenna patterns applied. Otherwise, apply the proper detector anntenna patterns and return the resultant series hf = FFT[F+h+ + Fxhx].
        """

        # FIXME: This is overkill for BTLWNB, and won't work entirely for
        # cosmic strings
        sampling_rate = 4 * (self.frequency + (self.bandwidth or 0))
        sampling_rate = 2**(int(math.log(sampling_rate, 2) + 1))
        self.__get_fwdplan(sampling_rate, deltaF)

        if detector is not None:
            h = self.time_series(sampling_rate, detector)
        else:
            hp, hx = self.time_series(sampling_rate, detector)
            h = lal.CreateREAL8TimeSeries(name="TD signal",
                                          epoch=hp.epoch,
                                          f0=0,
                                          deltaT=hp.deltaT,
                                          sampleUnits=lal.DimensionlessUnit,
                                          length=hp.data.length)
            h.data.data = hp.data.data + hx.data.data

        # zero pad
        needed_samps = int(sampling_rate / deltaF)
        prevlen = h.data.length
        if h.data.length < needed_samps:
            h = lal.ResizeREAL8TimeSeries(h, 0, needed_samps)
        elif h.data.length > needed_samps:
            h = lal.ResizeREAL8TimeSeries(h, h.data.length - needed_samps,
                                          needed_samps)

        # adjust heterodyne frequency to match flow
        hf = lal.CreateCOMPLEX16FrequencySeries(
            name="FD signal",
            epoch=h.epoch,
            f0=0,
            deltaF=deltaF,
            sampleUnits=lal.DimensionlessUnit,
            length=int(h.data.length / 2 + 1))

        # Forward FFT
        lal.REAL8TimeFreqFFT(hf, h, self._fwdplan)
        return hf
예제 #17
0
    def add_quadrature_phase(fseries, n):
        """
		From the Fourier transform of a real-valued function of
		time, compute and return the Fourier transform of the
		complex-valued function of time whose real component is the
		original time series and whose imaginary component is the
		quadrature phase of the real part.  fseries is a LAL
		COMPLEX16FrequencySeries and n is the number of samples in
		the original time series.
		"""
        #
        # positive frequencies include Nyquist if n is even
        #

        have_nyquist = not (n % 2)

        #
        # shuffle frequency bins
        #

        positive_frequencies = numpy.array(fseries.data.data)  # work with copy
        positive_frequencies[0] = 0  # set DC to zero
        zeros = numpy.zeros((len(positive_frequencies), ), dtype="cdouble")
        if have_nyquist:
            # complex transform never includes positive Nyquist
            positive_frequencies = positive_frequencies[:-1]

        #
        # prepare output frequency series
        #

        out_fseries = lal.CreateCOMPLEX16FrequencySeries(
            name=fseries.name,
            epoch=fseries.epoch,
            f0=fseries.f0,  # caution: only 0 is supported
            deltaF=fseries.deltaF,
            sampleUnits=fseries.sampleUnits,
            length=len(zeros) + len(positive_frequencies) - 1)
        out_fseries.data.data = numpy.concatenate(
            (zeros, 2 * positive_frequencies[1:]))

        return out_fseries
예제 #18
0
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
예제 #19
0
def colored_noise(epoch, duration, sample_rate, psd):
    """Generate a REAL8TimeSeries containing duration seconds of colored
    Gaussian noise at the given sample rate, with the start time given by
    epoch. psd should be an instance of REAL8FrequencySeries containing a
    discretely sample power spectrum with f0=0, deltaF=1/duration, and a length
    of ((duration * sample_rate) // 2 + 1) samples.
    """
    data_length = duration * sample_rate
    plan = CreateReverseREAL8FFTPlan(data_length, 0)
    x = lal.CreateREAL8TimeSeries(
        None, lal.LIGOTimeGPS(0), 0, 0, lal.DimensionlessUnit, data_length)
    xf = lal.CreateCOMPLEX16FrequencySeries(
        None, epoch, 0, 1 / duration,
        lal.DimensionlessUnit, data_length // 2 + 1)
    white_noise = (np.random.randn(len(xf.data.data)) +
                   np.random.randn(len(xf.data.data)) * 1j)

    # On line 1288 of lal's AverageSpectrum.c, in the code comments for
    # XLALWhitenCOMPLEX8FrequencySeries, it says that according to the LAL
    # conventions a whitened frequency series should consist of bins whose
    # real and imaginary parts each have a variance of 1/2.
    white_noise /= np.sqrt(2)

    # The factor of sqrt(2 * psd.deltaF) comes from the value of 'norm' on
    # line 1362 of AverageSpectrum.c.
    xf.data.data = white_noise * np.sqrt(psd.data.data / (2 * psd.deltaF))

    # Detrend the data: no DC component.
    xf.data.data[0] = 0

    # Return to time domain.
    lal.REAL8FreqTimeFFT(x, xf, plan)

    # Copy over metadata.
    x.epoch = epoch
    x.sampleUnits = lal.StrainUnit

    # Done.
    return x
def simulate_snr(ra,
                 dec,
                 psi,
                 inc,
                 distance,
                 epoch,
                 gmst,
                 H,
                 S,
                 response,
                 location,
                 measurement_error='zero-noise'):
    from scipy.interpolate import interp1d

    from ..bayestar import filter
    from ..bayestar.interpolation import interpolate_max

    duration = 0.1

    # Calculate whitened template autocorrelation sequence.
    HS = filter.signal_psd_series(H, S)
    n = len(HS.data.data)
    acor, sample_rate = filter.autocorrelation(HS, duration)

    # Calculate time, amplitude, and phase.
    u = np.cos(inc)
    u2 = np.square(u)
    signal_model = filter.SignalModel(HS)
    horizon = signal_model.get_horizon_distance()
    Fplus, Fcross = lal.ComputeDetAMResponse(response, ra, dec, psi, gmst)
    toa = lal.TimeDelayFromEarthCenter(location, ra, dec, epoch)
    z = (0.5 * (1 + u2) * Fplus + 1j * u * Fcross) * horizon / distance

    # Calculate complex autocorrelation sequence.
    snr_series = z * np.concatenate((acor[:0:-1].conj(), acor))

    # If requested, add noise.
    if measurement_error == 'gaussian-noise':
        sigmasq = 4 * np.sum(HS.deltaF * np.abs(HS.data.data))
        amp = 4 * n * HS.deltaF**0.5 * np.sqrt(HS.data.data / sigmasq)
        N = lal.CreateCOMPLEX16FrequencySeries('', HS.epoch, HS.f0, HS.deltaF,
                                               HS.sampleUnits, n)
        N.data.data = amp * (np.random.randn(n) + 1j * np.random.randn(n))
        noise_term, sample_rate_2 = filter.autocorrelation(N,
                                                           2 * duration -
                                                           1 / sample_rate,
                                                           normalize=False)
        assert sample_rate == sample_rate_2
        snr_series += noise_term

    # Shift SNR series to the nearest sample.
    int_samples, frac_samples = divmod(
        (1e-9 * epoch.gpsNanoSeconds + toa) * sample_rate, 1)
    if frac_samples > 0.5:
        int_samples += 1
        frac_samples -= 1
    epoch = lal.LIGOTimeGPS(epoch.gpsSeconds, 0)
    n = len(acor) - 1
    mprime = np.arange(-n, n + 1)
    m = mprime + frac_samples
    re, im = (interp1d(m, x, kind='cubic', bounds_error=False,
                       fill_value=0)(mprime)
              for x in (snr_series.real, snr_series.imag))
    snr_series = re + 1j * im

    # Find the trigger values.
    i_nearest = np.argmax(np.abs(
        snr_series[n - n // 2:n + n // 2 + 1])) + n - n // 2
    i_interp, z_interp = interpolate_max(i_nearest,
                                         snr_series,
                                         n // 2,
                                         method='lanczos')
    toa = epoch + (int_samples + i_interp - n) / sample_rate
    snr = np.abs(z_interp)
    phase = np.angle(z_interp)

    # Shift and truncate the SNR time series.
    epoch += (int_samples + i_nearest - n - n // 2) / sample_rate
    snr_series = snr_series[(i_nearest - n // 2):(i_nearest + n // 2 + 1)]
    tseries = lal.CreateCOMPLEX8TimeSeries('snr', epoch, 0, 1 / sample_rate,
                                           lal.DimensionlessUnit,
                                           len(snr_series))
    tseries.data.data = snr_series
    return horizon, snr, phase, toa, tseries
예제 #21
0
    def _compute_waveform(self, df, f_final):
        # Time domain, so compute then FFT
        # need to compute dt from df, duration
        sample_rate = 2**np.ceil(np.log2(2 * f_final))
        dt = 1. / sample_rate

        # Generate waveform in time domain
        hplus, hcross = lalsim.SimInspiralSpinTaylorT4(
            0,  # GW phase at reference freq (rad)
            1,  # tail gauge term (default = 1)
            dt,  # sampling interval (s)
            self.m1 * lal.MSUN_SI,  # mass of companion 1 (kg)
            self.m2 * lal.MSUN_SI,  # mass of companion 2 (kg)
            self.bank.flow,  # start GW frequency (Hz)
            self.bank.
            flow,  # reference GW frequency at which phase is set (Hz)
            1e6 * PC_SI,  # distance of source (m)
            self.s1x,  # initial value of S1x
            self.s1y,  # initial value of S1y
            self.s1z,  # initial value of S1z
            self.s2x,  # initial value of S2x
            self.s2y,  # initial value of S2y
            self.s2z,  # initial value of S2z
            np.sin(self.inclination),  # initial value of LNhatx
            0,  # initial value of LNhaty
            np.cos(self.inclination),  # initial value of LNhatz
            np.cos(self.inclination),  # initial value of E1x
            0,  # initial value of E1y
            -np.sin(self.inclination),  # initial value of E1z
            0,  # tidal deformability of mass 1
            0,  # tidal deformability of mass 2
            1,  # phenom. parameter describing induced quad. moment of body 1 (=1 for BHs, ~2-12 for NSs)
            1,  # phenom. parameter describing induced quad. moment of body 2 (=1 for BHs, ~2-12 for NSs)
            7,  # twice PN spin order
            0,  # twice PN tidal order
            7,  # twice PN phase order
            0  # twice PN amplitude order
        )

        # project onto detector
        hoft = project_hplus_hcross(hplus, hcross, self.theta, self.phi,
                                    self.psi)

        # zero-pad up to 1/df
        N = ceil_pow_2(int(sample_rate / df))
        hoft = lal.ResizeREAL8TimeSeries(hoft, 0, N)

        # taper
        lalsim.SimInspiralREAL8WaveTaper(hoft.data,
                                         lalsim.SIM_INSPIRAL_TAPER_STARTEND)

        # create vector to hold output and plan
        htilde = lal.CreateCOMPLEX16FrequencySeries("h(f)", hoft.epoch,
                                                    hoft.f0, df, lal.HertzUnit,
                                                    int(N / 2 + 1))
        fftplan = lal.CreateForwardREAL8FFTPlan(N, 0)

        # do the fft
        lal.REAL8TimeFreqFFT(htilde, hoft, fftplan)

        return htilde
예제 #22
0
def generate_template(template_bank_row,
                      approximant,
                      sample_rate,
                      duration,
                      f_low,
                      f_high,
                      amporder=0,
                      order=7,
                      fwdplan=None,
                      fworkspace=None):
    """
	Generate a single frequency-domain template, which
	1. is band-limited between f_low and f_high,
	2. has an IFFT which is duration seconds long and
	3. has an IFFT which is sampled at sample_rate Hz
	"""
    if approximant not in templates.gstlal_approximants:
        raise ValueError("Unsupported approximant given %s" % approximant)
    assert f_high <= sample_rate // 2

    # FIXME use hcross somday?
    # We don't here because it is not guaranteed to be orthogonal
    # and we add orthogonal phase later

    parameters = {}
    parameters['m1'] = lal.MSUN_SI * template_bank_row.mass1
    parameters['m2'] = lal.MSUN_SI * template_bank_row.mass2
    parameters['S1x'] = template_bank_row.spin1x
    parameters['S1y'] = template_bank_row.spin1y
    parameters['S1z'] = template_bank_row.spin1z
    parameters['S2x'] = template_bank_row.spin2x
    parameters['S2y'] = template_bank_row.spin2y
    parameters['S2z'] = template_bank_row.spin2z
    parameters['distance'] = 1.e6 * lal.PC_SI
    parameters['inclination'] = 0.
    parameters['phiRef'] = 0.
    parameters['longAscNodes'] = 0.
    parameters['eccentricity'] = 0.
    parameters['meanPerAno'] = 0.
    parameters['deltaF'] = 1.0 / duration
    parameters['f_min'] = f_low
    parameters['f_max'] = f_high
    parameters['f_ref'] = 0.
    parameters['LALparams'] = None
    parameters['approximant'] = lalsim.GetApproximantFromString(
        str(approximant))

    hplus, hcross = lalsim.SimInspiralFD(**parameters)
    assert len(hplus.data.data) == int(round(f_high * duration)) + 1
    # pad the output vector if the sample rate was higher than the
    # requested final frequency
    if f_high < sample_rate / 2:
        fseries = lal.CreateCOMPLEX16FrequencySeries(
            name=hplus.name,
            epoch=hplus.epoch,
            f0=hplus.f0,
            deltaF=hplus.deltaF,
            length=int(round(sample_rate * duration)) // 2 + 1,
            sampleUnits=hplus.sampleUnits)
        fseries.data.data = numpy.zeros(fseries.data.length)
        fseries.data.data[:hplus.data.length] = hplus.data.data[:]
        hplus = fseries
    return hplus
예제 #23
0
    def __init__(self,
                 template_table,
                 approximant,
                 psd,
                 f_low,
                 time_slices,
                 autocorrelation_length=None,
                 fhigh=None):
        self.template_table = template_table
        self.approximant = approximant
        self.f_low = f_low
        self.time_slices = time_slices
        self.autocorrelation_length = autocorrelation_length
        self.fhigh = fhigh
        self.sample_rate_max = max(time_slices["rate"])
        self.duration = max(time_slices["end"])
        self.length_max = int(round(self.duration * self.sample_rate_max))

        if self.fhigh is None:
            self.fhigh = self.sample_rate_max / 2.
        # Some input checking to avoid incomprehensible error messages
        if not self.template_table:
            raise ValueError("template list is empty")
        if self.f_low < 0.:
            raise ValueError("f_low must be >= 0. %s" % repr(self.f_low))

        # working f_low to actually use for generating the waveform.  pick
        # template with lowest chirp mass, compute its duration starting
        # from f_low;  the extra time is 10% of this plus 3 cycles (3 /
        # f_low);  invert to obtain f_low corresponding to desired padding.
        # NOTE:  because SimInspiralChirpStartFrequencyBound() does not
        # account for spin, we set the spins to 0 in the call to
        # SimInspiralChirpTimeBound() regardless of the component's spins.
        template = min(self.template_table, key=lambda row: row.mchirp)
        tchirp = lalsim.SimInspiralChirpTimeBound(self.f_low,
                                                  template.mass1 * lal.MSUN_SI,
                                                  template.mass2 * lal.MSUN_SI,
                                                  0., 0.)
        self.working_f_low = lalsim.SimInspiralChirpStartFrequencyBound(
            1.1 * tchirp + 3. / self.f_low, template.mass1 * lal.MSUN_SI,
            template.mass2 * lal.MSUN_SI)

        # Add duration of PSD to template length for PSD ringing, round up to power of 2 count of samples
        self.working_length = templates.ceil_pow_2(self.length_max +
                                                   round(1. / psd.deltaF *
                                                         self.sample_rate_max))
        self.working_duration = float(
            self.working_length) / self.sample_rate_max

        if psd is not None:
            # Smooth the PSD and interpolate to required resolution
            self.psd = condition_psd(psd,
                                     1.0 / self.working_duration,
                                     minfs=(self.working_f_low, self.f_low),
                                     maxfs=(self.sample_rate_max / 2.0 * 0.90,
                                            self.sample_rate_max / 2.0))

        if FIR_WHITENER:
            # Compute a frequency response of the time-domain whitening kernel and effectively taper the psd by zero-ing some elements for a FIR kernel
            self.kernel_fseries = taperzero_fseries(create_FIR_whitener_kernel(self.working_length, self.working_duration, self.sample_rate_max, self.psd),\
                        minfs = (self.working_f_low, self.f_low),\
                        maxfs = (self.sample_rate_max / 2.0 * 0.90, self.sample_rate_max / 2.0)\
                       )

        self.revplan = lal.CreateReverseCOMPLEX16FFTPlan(
            self.working_length, 1)
        self.fwdplan = lal.CreateForwardREAL8FFTPlan(self.working_length, 1)
        self.tseries = lal.CreateCOMPLEX16TimeSeries(
            name="timeseries",
            epoch=LIGOTimeGPS(0.),
            f0=0.,
            deltaT=1.0 / self.sample_rate_max,
            length=self.working_length,
            sampleUnits=lal.Unit("strain"))
        self.fworkspace = lal.CreateCOMPLEX16FrequencySeries(
            name="template",
            epoch=LIGOTimeGPS(0),
            f0=0.0,
            deltaF=1.0 / self.working_duration,
            length=self.working_length // 2 + 1,
            sampleUnits=lal.Unit("strain s"))

        # Calculate the maximum ring down time or maximum shift time
        if approximant in templates.gstlal_IMR_approximants:
            self.max_ringtime = max([
                chirptime.ringtime(
                    row.mass1 * lal.MSUN_SI + row.mass2 * lal.MSUN_SI,
                    chirptime.overestimate_j_from_chi(
                        max(row.spin1z, row.spin2z)))
                for row in self.template_table
            ])
        else:
            if self.sample_rate_max > 2. * self.fhigh:
                # Calculate the maximum time we need to shift the early warning
                # waveforms forward by, calculated by the 3.5 approximation from
                # fhigh to ISCO.
                self.max_shift_time = max([
                    spawaveform.chirptime(
                        row.mass1, row.mass2, 7, fhigh, 0.,
                        spawaveform.computechi(row.mass1, row.mass2,
                                               row.spin1z, row.spin2z))
                    for row in self.template_table
                ])
예제 #24
0
# resize if necessary for FFT
if h_wnb.data.length < needed_samps:
	h_wnb = lal.ResizeREAL8TimeSeries( h_wnb, 0, needed_samps )
elif h_wnb.data.length > needed_samps:
	h_wnb = lal.ResizeREAL8TimeSeries( h_wnb, h_wnb.data.length-needed_samps, needed_samps )

if h_sg.data.length < needed_samps:
	h_sg = lal.ResizeREAL8TimeSeries( h_sg, 0, needed_samps )
elif h_sg.data.length > needed_samps:
	h_sg = lal.ResizeREAL8TimeSeries( h_sg, h_sg.data.length-needed_samps, needed_samps )

hf_wnb = lal.CreateCOMPLEX16FrequencySeries(
									name = "m1",
									epoch = h_wnb.epoch,
									f0 = 0,
									deltaF = deltaF,
									sampleUnits = lal.lalDimensionlessUnit,
									length = h_wnb.data.length/2 + 1
									)

hf_sg = lal.CreateCOMPLEX16FrequencySeries(
										name = "n1",
										epoch = h_sg.epoch,
										f0 = 0,
										deltaF = deltaF,
										sampleUnits = lal.lalDimensionlessUnit,
										length = h_sg.data.length/2 + 1
										)

fwdlen = needed_samps
예제 #25
0
def analyze_event(P_list,
                  indx_event,
                  data_dict,
                  psd_dict,
                  fmax,
                  opts,
                  inv_spec_trunc_Q=inv_spec_trunc_Q,
                  T_spec=T_spec):
    nEvals = 0
    P = P_list[indx_event]
    # Precompute
    t_window = 0.15
    rholms_intp, cross_terms, cross_terms_V, rholms, rest = factored_likelihood.PrecomputeLikelihoodTerms(
        fiducial_epoch,
        t_window,
        P,
        data_dict,
        psd_dict,
        opts.l_max,
        fmax,
        False,
        inv_spec_trunc_Q,
        T_spec,
        NR_group=NR_template_group,
        NR_param=NR_template_param,
        use_external_EOB=opts.use_external_EOB,
        nr_lookup=opts.nr_lookup,
        nr_lookup_valid_groups=opts.nr_lookup_group,
        perturbative_extraction=opts.nr_perturbative_extraction,
        use_provided_strain=opts.nr_use_provided_strain,
        hybrid_use=opts.nr_hybrid_use,
        hybrid_method=opts.nr_hybrid_method,
        ROM_group=opts.rom_group,
        ROM_param=opts.rom_param,
        ROM_use_basis=opts.rom_use_basis,
        verbose=opts.verbose,
        quiet=not opts.verbose,
        ROM_limit_basis_size=opts.rom_limit_basis_size_to,
        no_memory=opts.no_memory,
        skip_interpolation=opts.vectorized)

    # Only allocate the FFT plans ONCE
    ifo0 = psd_dict.keys()[0]
    npts = data_dict[ifo0].data.length
    print(" Allocating FFT forward, reverse plans ", npts)
    fwdplan = lal.CreateForwardREAL8FFTPlan(npts, 0)
    revplan = lal.CreateReverseREAL8FFTPlan(npts, 0)

    for ifo in psd_dict:
        # Plot PSDs
        plt.figure(99)  # PSD figure)
        fvals = psd_dict[ifo].f0 + np.arange(
            psd_dict[ifo].data.length) * psd_dict[ifo].deltaF
        plt.plot(fvals, np.log10(np.sqrt(psd_dict[ifo].data.data)), label=ifo)
        plt.figure(88)
        plt.plot(fvals, fvals**(-14. / 6.) / psd_dict[ifo].data.data)
        plt.figure(1)

        # Plot inverse spectrum filters
        #     - see lalsimutils code for inv_spec_trunc_Q , copied verbatim
        plt.figure(98)
        IP_here = lalsimutils.ComplexOverlap(P.fmin, fmax, 1. / 2 / P.deltaT,
                                             P.deltaF, psd_dict[ifo], False,
                                             inv_spec_trunc_Q, T_spec)
        WFD = lal.CreateCOMPLEX16FrequencySeries('FD root inv. spec.',
                                                 lal.LIGOTimeGPS(0.), 0.,
                                                 IP_here.deltaF,
                                                 lal.DimensionlessUnit,
                                                 IP_here.len1side)
        WTD = lal.CreateREAL8TimeSeries('TD root inv. spec.',
                                        lal.LIGOTimeGPS(0.), 0.,
                                        IP_here.deltaT, lal.DimensionlessUnit,
                                        IP_here.len2side)
        print(ifo, IP_here.len2side)
        #        if not(fwdplan is None):
        WFD.data.data[:] = np.sqrt(IP_here.weights)  # W_FD is 1/sqrt(S_n(f))
        WFD.data.data[0] = WFD.data.data[-1] = 0.  # zero 0, f_Nyq bins
        lal.REAL8FreqTimeFFT(WTD, WFD, revplan)  # IFFT to TD
        tvals = IP_here.deltaT * np.arange(IP_here.len2side)
        plt.plot(tvals, np.log10(np.abs(WTD.data.data)), label=ifo)

        # Plot Q's
        plt.figure(1)
        plt.clf()
        for mode in rholms[ifo]:
            Q_here = rholms[ifo][mode]
            tvals = lalsimutils.evaluate_tvals(Q_here) - P.tref
            plt.plot(tvals,
                     np.abs(Q_here.data.data),
                     label=ifo + str(mode[0]) + "," + str(mode[1]))
        plt.legend()
        plt.xlabel("t (s)")
        plt.xlim(-0.1, 0.1)
        plt.xlabel("$Q_{lm}$")
        plt.title(ifo)
        plt.savefig(ifo + "_Q.png")

    plt.figure(99)
    plt.legend()
    plt.xlabel("f(Hz)")
    plt.ylabel(r'$\sqrt{S_h}$')
    plt.ylim(-24, -21)
    plt.savefig("PSD_plots.png")
    plt.xlim(5, 800)
    plt.savefig("PSD_plots_detail.png")
    plt.xlim(10, 400)
    plt.ylim(-23.5, -22)
    plt.savefig("PSD_plots_detail_fine.png")
    plt.figure(98)
    plt.legend()
    plt.xlabel("t (s)")
    plt.savefig("PSD_inv_plots.png")
    plt.figure(88)
    plt.legend()
    plt.xlabel("f (Hz)")
    plt.ylabel(r'$(S_h f^{15/6})^{-1}$')
    plt.savefig("PSD_weight_f.png")