Beispiel #1
0
    def fourier_segments(self):
        """ Return a list of the FFT'd segments.

        Return the list of FrequencySeries. Additional properties are
        added that describe the strain segment. The property 'analyze'
        is a slice corresponding to the portion of the time domain equivelant
        of the segment to analyze for triggers. The value 'cumulative_index'
        indexes from the beginning of the original strain series.
        """
        if not self._fourier_segments:
            self._fourier_segments = []
            for seg_slice, ana in zip(self.segment_slices,
                                      self.analyze_slices):
                if seg_slice.start >= 0 and seg_slice.stop <= len(self.strain):
                    freq_seg = make_frequency_series(self.strain[seg_slice])
                # Assume that we cannot have a case where we both zero-pad on
                # both sides
                elif seg_slice.start < 0:
                    strain_chunk = self.strain[:seg_slice.stop]
                    strain_chunk.prepend_zeros(-seg_slice.start)
                    freq_seg = make_frequency_series(strain_chunk)
                elif seg_slice.stop > len(self.strain):
                    strain_chunk = self.strain[seg_slice.start:]
                    strain_chunk.append_zeros(seg_slice.stop -
                                              len(self.strain))
                    freq_seg = make_frequency_series(strain_chunk)
                freq_seg.analyze = ana
                freq_seg.cumulative_index = seg_slice.start + ana.start
                freq_seg.seg_slice = seg_slice
                self._fourier_segments.append(freq_seg)

        return self._fourier_segments
Beispiel #2
0
    def fourier_segments(self):
        """ Return a list of the FFT'd segments.

        Return the list of FrequencySeries. Additional properties are
        added that describe the strain segment. The property 'analyze'
        is a slice corresponding to the portion of the time domain equivelant
        of the segment to analyze for triggers. The value 'cumulative_index'
        indexes from the beginning of the original strain series.
        """
        if not self._fourier_segments:
            self._fourier_segments = []
            for seg_slice, ana in zip(self.segment_slices, self.analyze_slices):
                if seg_slice.start >= 0 and seg_slice.stop <= len(self.strain):
                    freq_seg = make_frequency_series(self.strain[seg_slice])
                # Assume that we cannot have a case where we both zero-pad on
                # both sides
                elif seg_slice.start < 0:
                    strain_chunk = self.strain[:seg_slice.stop]
                    strain_chunk.prepend_zeros(-seg_slice.start)
                    freq_seg = make_frequency_series(strain_chunk)
                elif seg_slice.stop > len(self.strain):
                    strain_chunk = self.strain[seg_slice.start:]
                    strain_chunk.append_zeros(seg_slice.stop - len(self.strain))
                    freq_seg = make_frequency_series(strain_chunk)
                freq_seg.analyze = ana
                freq_seg.cumulative_index = seg_slice.start + ana.start
                freq_seg.seg_slice = seg_slice
                self._fourier_segments.append(freq_seg)

        return self._fourier_segments
Beispiel #3
0
def inner(vec1,
          vec2,
          psd=None,
          low_frequency_cutoff=None,
          high_frequency_cutoff=None,
          v1_norm=None,
          v2_norm=None):

    htilde = pf.make_frequency_series(vec1)
    stilde = pf.make_frequency_series(vec2)

    N = (len(htilde) - 1) * 2

    global _snr
    _snr = None
    if _snr is None or _snr.dtype != htilde.dtype or len(_snr) != N:
        _snr = pt.zeros(N, dtype=pt.complex_same_precision_as(vec1))
        snr, corr, snr_norm = pf.matched_filter_core(htilde,
                                                     stilde,
                                                     psd,
                                                     low_frequency_cutoff,
                                                     high_frequency_cutoff,
                                                     v1_norm,
                                                     out=_snr)
    if v2_norm is None:
        v2_norm = pf.sigmasq(stilde, psd, low_frequency_cutoff,
                             high_frequency_cutoff)

    snr.data = snr.data * snr_norm / np.sqrt(v2_norm)

    return snr
Beispiel #4
0
    def test_distance_scaling(self):
        #""" Check that the waveform is consistent under distance changes
        #"""
        distance = 1e6
        tolerance = 1e-5
        fac = 10

        hpc, hcc = get_waveform(self.p, distance=distance)
        hpm, hcm = get_waveform(self.p, distance=distance * fac)
        hpf, hcf = get_waveform(self.p, distance=distance * fac * fac)
        hpn, hcn = get_waveform(self.p, distance=distance / fac)

        f = pylab.figure()
        pylab.axes([.1, .2, 0.8, 0.70])
        htilde = make_frequency_series(hpc)
        pylab.loglog(htilde.sample_frequencies, abs(htilde), label="D")

        htilde = make_frequency_series(hpm)
        pylab.loglog(htilde.sample_frequencies,
                     abs(htilde),
                     label="D * %s" % fac)

        htilde = make_frequency_series(hpf)
        pylab.loglog(htilde.sample_frequencies,
                     abs(htilde),
                     label="D * %s" % (fac * fac))

        htilde = make_frequency_series(hpn)
        pylab.loglog(htilde.sample_frequencies,
                     abs(htilde),
                     label="D / %s" % fac)

        pylab.title("Vary %s distance, $\\tilde{h}$+" % self.p.approximant)
        pylab.xlabel("GW Frequency (Hz)")
        pylab.ylabel("GW Strain")
        pylab.legend()
        pylab.xlim(xmin=self.p.f_lower)

        info = self.version_txt
        pylab.figtext(0.05, .05, info)

        if self.save_plots:
            pname = self.plot_dir + "/%s-distance-scaling.png" % self.p.approximant
            pylab.savefig(pname)

        if self.show_plots:
            pylab.show()
        else:
            pylab.close(f)

        self.assertTrue(
            hpc.almost_equal_elem(hpm * fac, tolerance, relative=True))
        self.assertTrue(
            hpc.almost_equal_elem(hpf * fac * fac, tolerance, relative=True))
        self.assertTrue(
            hpc.almost_equal_elem(hpn / fac, tolerance, relative=True))
Beispiel #5
0
def power_chisq(template,
                data,
                num_bins,
                psd,
                low_frequency_cutoff=None,
                high_frequency_cutoff=None,
                return_bins=False):
    """Calculate the chisq timeseries

    Parameters
    ----------
    template: FrequencySeries or TimeSeries
        A time or frequency series that contains the filter template.
    data: FrequencySeries or TimeSeries
        A time or frequency series that contains the data to filter. The length
        must be commensurate with the template.
        (EXPLAINME - does this mean 'the same as' or something else?)
    num_bins: int
        The number of frequency bins used for chisq. The number of statistical
        degrees of freedom ('dof') is 2*num_bins-2.
    psd: FrequencySeries
        The psd of the data.
    low_frequency_cutoff: {None, float}, optional
        The low frequency cutoff for the filter
    high_frequency_cutoff: {None, float}, optional
        The high frequency cutoff for the filter
    return_bins: {boolean, False}, optional
        Return a list of the individual chisq bins

    Returns
    -------
    chisq: TimeSeries
        TimeSeries containing the chisq values for all times.
    """
    htilde = make_frequency_series(template)
    stilde = make_frequency_series(data)

    bins = power_chisq_bins(htilde, num_bins, psd, low_frequency_cutoff,
                            high_frequency_cutoff)
    corra = zeros((len(htilde) - 1) * 2, dtype=htilde.dtype)
    total_snr, corr, tnorm = matched_filter_core(htilde,
                                                 stilde,
                                                 psd,
                                                 low_frequency_cutoff,
                                                 high_frequency_cutoff,
                                                 corr_out=corra)

    return power_chisq_from_precomputed(corr,
                                        total_snr,
                                        tnorm,
                                        bins,
                                        return_bins=return_bins)
Beispiel #6
0
    def test_distance_scaling(self):   
        #""" Check that the waveform is consistent under distance changes
        #"""     
        distance = 1e6
        tolerance = 1e-5
        fac = 10
    
        hpc, hcc = get_waveform(self.p, distance=distance)
        hpm, hcm = get_waveform(self.p, distance=distance*fac)
        hpf, hcf = get_waveform(self.p, distance=distance*fac*fac)
        hpn, hcn = get_waveform(self.p, distance=distance/fac)
        
        f = pylab.figure()
        pylab.axes([.1, .2, 0.8, 0.70])
        htilde = make_frequency_series(hpc)
        pylab.loglog(htilde.sample_frequencies, abs(htilde), label="D")
        
        htilde = make_frequency_series(hpm)
        pylab.loglog(htilde.sample_frequencies, abs(htilde), label="D * %s" %fac)
       
        htilde = make_frequency_series(hpf)
        pylab.loglog(htilde.sample_frequencies, abs(htilde), label="D * %s" %(fac*fac))
        
        htilde = make_frequency_series(hpn)
        pylab.loglog(htilde.sample_frequencies, abs(htilde), label="D / %s" %fac)
            
        pylab.title("Vary %s distance, $\\tilde{h}$+" % self.p.approximant)
        pylab.xlabel("GW Frequency (Hz)")
        pylab.ylabel("GW Strain")
        pylab.legend()
        pylab.xlim(xmin=self.p.f_lower)
        
        info = self.version_txt
        pylab.figtext(0.05, .05, info)
        
        if self.save_plots:
            pname = self.plot_dir + "/%s-distance-scaling.png" % self.p.approximant
            pylab.savefig(pname)

        if self.show_plots:
            pylab.show()
        else:
            pylab.close(f)
            
        self.assertTrue(hpc.almost_equal_elem(hpm * fac, tolerance, relative=True))
        self.assertTrue(hpc.almost_equal_elem(hpf * fac * fac, tolerance, relative=True))
        self.assertTrue(hpc.almost_equal_elem(hpn / fac, tolerance, relative=True))
Beispiel #7
0
def power_chisq(template, data, num_bins, psd,
                low_frequency_cutoff=None,
                high_frequency_cutoff=None,
                return_bins=False):
    """Calculate the chisq timeseries

    Parameters
    ----------
    template: FrequencySeries or TimeSeries
        A time or frequency series that contains the filter template.
    data: FrequencySeries or TimeSeries
        A time or frequency series that contains the data to filter. The length
        must be commensurate with the template.
        (EXPLAINME - does this mean 'the same as' or something else?)
    num_bins: int
        The number of bins in the chisq. Note that the dof goes as 2*num_bins-2.
    psd: FrequencySeries
        The psd of the data.
    low_frequency_cutoff: {None, float}, optional
        The low frequency cutoff for the filter
    high_frequency_cutoff: {None, float}, optional
        The high frequency cutoff for the filter
    return_bins: {boolean, False}, optional
        Return a list of the individual chisq bins

    Returns
    -------
    chisq: TimeSeries
        TimeSeries containing the chisq values for all times.
    """
    htilde = make_frequency_series(template)
    stilde = make_frequency_series(data)

    bins = power_chisq_bins(htilde, num_bins, psd, low_frequency_cutoff,
                            high_frequency_cutoff)
    corra = zeros((len(htilde)-1)*2, dtype=htilde.dtype)
    total_snr, corr, tnorm = matched_filter_core(htilde, stilde, psd,
                           low_frequency_cutoff, high_frequency_cutoff,
                           corr_out=corra)

    return power_chisq_from_precomputed(corr, total_snr, tnorm, bins, return_bins=return_bins)
Beispiel #8
0
    def fourier_segments(self):
        """ Return a list of the FFT'd segments.

        Return the list of FrequencySeries. Additional properties are
        added that describe the strain segment. The property 'analyze'
        is a slice corresponding to the portion of the time domain equivelant
        of the segment to analyze for triggers. The value 'cumulative_index'
        indexes from the beginning of the original strain series.
        """
        if not self._fourier_segments:
            self._fourier_segments = []
            for seg_slice, ana in zip(self.segment_slices, self.analyze_slices):
                freq_seg = make_frequency_series(self.strain[seg_slice])
                freq_seg.analyze = ana
                freq_seg.cumulative_index = seg_slice.start + ana.start
                self._fourier_segments.append(freq_seg)

        return self._fourier_segments
Beispiel #9
0
    def fourier_segments(self):
        """ Return a list of the FFT'd segments.

        Return the list of FrequencySeries. Additional properties are
        added that describe the strain segment. The property 'analyze'
        is a slice corresponding to the portion of the time domain equivelant
        of the segment to analyze for triggers. The value 'cumulative_index'
        indexes from the beginning of the original strain series.
        """
        if not self._fourier_segments:
            self._fourier_segments = []
            for seg_slice, ana in zip(self.segment_slices, self.analyze_slices):
                freq_seg = make_frequency_series(self.strain[seg_slice])
                freq_seg.analyze = ana
                freq_seg.cumulative_index = seg_slice.start + ana.start
                freq_seg.seg_slice = seg_slice
                self._fourier_segments.append(freq_seg)

        return self._fourier_segments
Beispiel #10
0
def get_waveform(approximant,
                 phase_order,
                 amplitude_order,
                 spin_order,
                 template_params,
                 start_frequency,
                 sample_rate,
                 length,
                 datafile=None,
                 verbose=False):
    #{{{
    print("IN hERE")
    delta_t = 1. / sample_rate
    delta_f = 1. / length
    filter_N = int(length)
    filter_n = filter_N / 2 + 1
    if approximant in fd_approximants() and 'Eccentric' not in approximant:
        print("NORMAL FD WAVEFORM for", approximant)
        delta_f = sample_rate / length
        hplus, hcross = get_fd_waveform(template_params,
                                        approximant=approximant,
                                        spin_order=spin_order,
                                        phase_order=phase_order,
                                        delta_f=delta_f,
                                        f_lower=start_frequency,
                                        amplitude_order=amplitude_order)
    elif approximant in td_approximants() and 'Eccentric' not in approximant:
        print("NORMAL TD WAVEFORM for", approximant)
        hplus, hcross = get_td_waveform(template_params,
                                        approximant=approximant,
                                        spin_order=spin_order,
                                        phase_order=phase_order,
                                        delta_t=1.0 / sample_rate,
                                        f_lower=start_frequency,
                                        amplitude_order=amplitude_order)
    elif 'EccentricIMR' in approximant:
        #{{{
        # Legacy support
        import sys
        sys.path.append('/home/kuma/grav/kuma/src/Eccentric_IMR/Codes/Python/')
        import EccentricIMR as Ecc
        try:
            mass1 = getattr(template_params, 'mass1')
            mass2 = getattr(template_params, 'mass2')
        except:
            raise RuntimeError("template_params does not have mass1 or mass2!")
        try:
            ecc = getattr(template_params, 'alpha1')
            if 'E0' in approximant: ecc = 0
            anom = getattr(template_params, 'alpha2')
            inc = getattr(template_params, 'inclination')
            rtrans = getattr(template_params, 'alpha')
            beta = 0
        except:
            raise RuntimeError(\
                  "template_params does not have alpha{,1,2} or inclination")
        tol = 1.e-16
        fmin = start_frequency
        sample_rate = sample_rate
        #
        print(" Using phase order: %d" % phase_order, file=sys.stdout)
        sys.stdout.flush()
        hplus, hcross = Ecc.generate_eccentric_waveform(mass1, mass2,\
                            ecc, anom, inc, beta,\
                            tol,\
                            r_transition=rtrans,\
                            phase_order=phase_order,\
                            fmin=fmin,\
                            sample_rate=sample_rate,\
                            inspiral_only=False)
        #}}}
    elif 'EccentricInspiral' in approximant:
        #{{{
        # Legacy support
        import sys
        sys.path.append('/home/kuma/grav/kuma/src/Eccentric_IMR/Codes/Python/')
        import EccentricIMR as Ecc
        try:
            mass1 = getattr(template_params, 'mass1')
            mass2 = getattr(template_params, 'mass2')
        except:
            raise RuntimeError("template_params does not have mass1 or mass2!")
        try:
            ecc = getattr(template_params, 'alpha1')
            if 'E0' in approximant: ecc = 0
            anom = getattr(template_params, 'alpha2')
            inc = getattr(template_params, 'inclination')
            beta = getattr(template_params, 'alpha')
        except:
            raise RuntimeError(\
                  "template_params does not have alpha{,1,2} or inclination")
        tol = 1.e-16
        fmin = start_frequency
        sample_rate = sample_rate
        #
        hplus, hcross = Ecc.generate_eccentric_waveform(mass1, mass2,\
                            ecc, anom, inc, beta,\
                            tol,\
                            phase_order=phase_order,\
                            fmin=fmin,\
                            sample_rate=sample_rate,\
                            inspiral_only=True)
        #}}}
    elif 'EccentricFD' in approximant:
        #{{{
        # Legacy support
        import lalsimulation as ls
        import lal
        delta_f = sample_rate / length
        try:
            mass1 = getattr(template_params, 'mass1')
            mass2 = getattr(template_params, 'mass2')
        except:
            raise RuntimeError("template_params does not have mass1 or mass2!")
        try:
            ecc = getattr(template_params, 'alpha1')
            if 'E0' in approximant: ecc = 0
            anom = getattr(template_params, 'alpha2')
            inc = getattr(template_params, 'inclination')
        except:
            raise RuntimeError(\
                  "template_params does not have alpha{1,2} or inclination")
        eccPar = ls.SimInspiralCreateTestGRParam("inclination_azimuth", inc)
        ls.SimInspiralAddTestGRParam(eccPar, "e_min", ecc)
        fmin = start_frequency
        fmax = sample_rate / 2
        #
        thp, thc = ls.SimInspiralChooseFDWaveform(0, delta_f,\
                        mass1*lal.MSUN_SI, mass2*lal.MSUN_SI,\
                        0,0,0,0,0,0,\
                        fmin, fmax, 0, 1.e6 * lal.PC_SI,\
                        inc, 0, 0, None, eccPar, -1, 7, ls.EccentricFD)
        hplus = FrequencySeries(thp.data.data[:],
                                delta_f=thp.deltaF,
                                epoch=thp.epoch)
        hcross = FrequencySeries(thc.data.data[:],
                                 delta_f=thc.deltaF,
                                 epoch=thc.epoch)
        #}}}
    elif 'FromDataFile' in approximant:
        #{{{
        # Legacy support
        if not os.path.exists(datafile):
            raise IOError("File %s not found!" % datafile)
        if verbose:
            print("Reading from data file %s" % datafile)

        # Figure out waveform parameters from filename
        #q_value, M_value, w_value, _, _ = EA.get_q_m_e_pn_o_from_filename(datafile)
        q_value, M_value, w_value = EA.get_q_m_e_from_filename(datafile)

        # Read data, down-sample (assume data file is more finely sampled than
        # needed, i.e. interpolation is NOT supported, nor will be)
        data = np.loadtxt(datafile)
        dt = data[1, 0] - data[0, 0]
        delta_t = 1. / sample_rate
        downsample_ratio = delta_t / dt
        if not approx_equal(downsample_ratio, np.int(downsample_ratio)):
            raise RuntimeError(
                "Cannot handling resampling at a fractional factor = %e" %
                downsample_ratio)
        elif verbose:
            print("Downsampling by a factor of %d" % int(downsample_ratio))
        h_real = TimeSeries(data[::int(downsample_ratio), 1] / DYN_RANGE_FAC,
                            delta_t=delta_t)
        h_imag = TimeSeries(data[::int(downsample_ratio), 2] / DYN_RANGE_FAC,
                            delta_t=delta_t)

        if verbose:
            print("max, min,len of h_real = ", max(h_real.data),
                  min(h_real.data), len(h_real.data))

        # Compute Strain
        tmplt_pars = template_params
        wav = generate_detector_strain(tmplt_pars, h_real, h_imag)
        wav = extend_waveform_TimeSeries(wav, filter_N)

        # Return TimeSeries with (m1, m2, w_value)
        m1, m2 = mtotal_eta_to_mass1_mass2(M_value,
                                           q_value / (1. + q_value)**2)
        htilde = make_frequency_series(wav)
        htilde = extend_waveform_FrequencySeries(htilde, filter_n)

        if verbose:
            print("ISNAN(htilde from file) = ", np.any(np.isnan(htilde.data)))
        return htilde, [m1, m2, w_value, dt]
        #}}}
    else:
        raise IOError(".. APPROXIMANT %s not found.." % approximant)
    ##
    hvec = hplus
    htilde = make_frequency_series(hvec)
    htilde = extend_waveform_FrequencySeries(htilde, filter_n)
    #
    print("type of hplus, hcross = ", type(hplus.data), type(hcross.data))
    if any(isnan(hplus.data)) or any(isnan(hcross.data)):
        print("..### %s hplus or hcross have NANS!!" % approximant)
    #
    if any(isinf(hplus.data)) or any(isinf(hcross.data)):
        print("..### %s hplus or hcross have INFS!!" % approximant)
    #
    if any(isnan(htilde.data)):
        print("..### %s Fourier transform htilde has NANS!!" % approximant)
    #
    if any(isinf(htilde.data)):
        print("..### %s Fourier transform htilde has INFS!!" % approximant)
    #
    return htilde
Beispiel #11
0
def calculate_faithfulness(m1, m2,
                           s1x=0, s1y=0, s1z=0,
                           s2x=0, s2y=0, s2z=0,
                           tc=0, phic=0,
                           ra=0, dec=0, polarization=0,
                           signal_approx='IMRPhenomD',
                           signal_file=None,
                           tmplt_approx='IMRPhenomC',
                           tmplt_file=None,
                           aligned_spin_tmplt_only=True,
                           non_spin_tmplt_only=False,
                           f_lower=15.0,
                           sample_rate=4096,
                           signal_duration=256,
                           psd_string='aLIGOZeroDetHighPower',
                           verbose=True,
                           debug=False):
    """
Calculates the match for a signal of given physical
parameters, as modelled by a given signal approximant, against
templates of another approximant.

This function allows turning off x,y components of
spin for templates.

IN PROGRESS: Adding facility to use "FromDataFile" waveforms
    """
    # {{{
    # 0) OPTION CHECKING
    if aligned_spin_tmplt_only:
        print(
            "WARNING: Spin components parallel to L allowed, others set to 0 in templates.")

    # 1) GENERATE FILTERING META-PARAMETERS
    filter_N = signal_duration * sample_rate
    filter_n = filter_N / 2 + 1
    delta_t = 1./sample_rate
    delta_f = 1./signal_duration
    # LIGO Noise PSD
    psd = from_string(psd_string, filter_n, delta_f, f_lower)

    # 2) GENERATE THE TARGET SIGNAL
    # Get the signal waveform first
    if signal_approx in pywf.fd_approximants():
        generator = pywfg.FDomainDetFrameGenerator(pywfg.FDomainCBCGenerator, 0,
                                                   variable_args=['mass1', 'mass2',
                                                                  'spin1x', 'spin1y', 'spin1z',
                                                                  'spin2x', 'spin2y', 'spin2z',
                                                                  'coa_phase',
                                                                  'tc', 'ra', 'dec', 'polarization'],
                                                   detectors=['H1'],
                                                   delta_f=delta_f, f_lower=f_lower,
                                                   approximant=signal_approx)
    elif signal_approx in pywf.td_approximants():
        generator = pywfg.TDomainDetFrameGenerator(pywfg.TDomainCBCGenerator, 0,
                                                   variable_args=['mass1', 'mass2',
                                                                  'spin1x', 'spin1y', 'spin1z',
                                                                  'spin2x', 'spin2y', 'spin2z',
                                                                  'coa_phase',
                                                                  'tc', 'ra', 'dec', 'polarization'],
                                                   detectors=['H1'],
                                                   delta_t=delta_t, f_lower=f_lower,
                                                   approximant=signal_approx)
    elif 'FromDataFile' in signal_approx:
        if os.path.getsize(signal_file) == 0:
            raise RuntimeError(
                " ERROR:...OOPS. Waveform file %s empty!!" % signal_file)
        try:
            _ = np.loadtxt(signal_file)
        except:
            raise RuntimeError(
                " WARNING: FAILURE READING DATA FROM %s.." % signal_file)

        waveform_params = lsctables.SimInspiral()
        waveform_params.latitude = 0
        waveform_params.longitude = 0
        waveform_params.polarization = 0
        waveform_params.spin1x = 0
        waveform_params.spin1y = 0
        waveform_params.spin1z = 0
        waveform_params.spin2x = 0
        waveform_params.spin2y = 0
        waveform_params.spin2z = 0
        # try:
        if True:
            if verbose:
                print(".. generating signal waveform ")
            signal_htilde, _params = get_waveform(signal_approx,
                                                  -1, -1, -1,
                                                  waveform_params,
                                                  f_lower,
                                                  sample_rate,
                                                  filter_N,
                                                  datafile=signal_file)
            print(".. generated signal waveform ")
            m1, m2, w_value, _ = _params
            waveform_params.mass1 = m1
            waveform_params.mass2 = m2
            signal_h = make_frequency_series(signal_htilde)
            signal_h = extend_waveform_FrequencySeries(signal_h, filter_n)
        # except: raise IOError("Approximant %s not found.." % signal_approx)
    else:
        raise IOError("Signal Approximant %s not found.." % signal_approx)
    if verbose:
        print("..Generating signal with masses = %3f, %.3f, spin1 = (%.3f, %.3f, %.3f), and  spin2 = (%.3f, %.3f, %.3f)" %
              (m1, m2, s1x, s1y, s1z, s2x, s2y, s2z))
        sys.stdout.flush()

    if signal_approx in pywf.fd_approximants():
        signal = generator.generate_from_args(m1, m2,
                                              s1x, s1y, s1z,
                                              s2x, s2y, s2z,
                                              phic, tc, ra, dec, polarization)
        # NOTE: SEOBNRv4 has extra high frequency content, it seems..
        if 'SEOBNRv4_ROM' in signal_approx or 'SEOBNRv2_ROM' in signal_approx:
            signal_h = extend_waveform_FrequencySeries(
                signal['H1'], filter_n, force_fit=True)
        else:
            signal_h = extend_waveform_FrequencySeries(signal['H1'], filter_n)
    elif signal_approx in pywf.td_approximants():
        signal = generator.generate_from_args(m1, m2,
                                              s1x, s1y, s1z,
                                              s2x, s2y, s2z,
                                              phic, tc, ra, dec, polarization)
        signal_h = make_frequency_series(signal['H1'])
        signal_h = extend_waveform_FrequencySeries(signal_h, filter_n)
    elif 'FromDataFile' in signal_approx:
        pass
    else:
        raise IOError("Signal Approximant %s not found.." % signal_approx)

    # 3) GENERATE THE TARGET TEMPLATE
    # Get the signal waveform first
    if tmplt_approx in pywf.fd_approximants():
        generator = pywfg.FDomainDetFrameGenerator(pywfg.FDomainCBCGenerator, 0,
                                                   variable_args=['mass1', 'mass2',
                                                                  'spin1x', 'spin1y', 'spin1z',
                                                                  'spin2x', 'spin2y', 'spin2z',
                                                                  'coa_phase',
                                                                  'tc', 'ra', 'dec', 'polarization'],
                                                   detectors=['H1'],
                                                   delta_f=delta_f, f_lower=f_lower,
                                                   approximant=tmplt_approx)
    elif tmplt_approx in pywf.td_approximants():
        generator = pywfg.TDomainDetFrameGenerator(pywfg.TDomainCBCGenerator, 0,
                                                   variable_args=['mass1', 'mass2',
                                                                  'spin1x', 'spin1y', 'spin1z',
                                                                  'spin2x', 'spin2y', 'spin2z',
                                                                  'coa_phase',
                                                                  'tc', 'ra', 'dec', 'polarization'],
                                                   detectors=['H1'],
                                                   delta_t=delta_t, f_lower=f_lower,
                                                   approximant=tmplt_approx)
    elif 'FromDataFile' in tmplt_approx:
        if os.path.getsize(tmplt_file) == 0:
            raise RuntimeError(
                " ERROR:...OOPS. Waveform file %s empty!!" % tmplt_file)
        try:
            _ = np.loadtxt(tmplt_file)
        except:
            raise RuntimeError(
                " WARNING: FAILURE READING DATA FROM %s.." % tmplt_file)

        waveform_params = lsctables.SimInspiral()
        waveform_params.latitude = 0
        waveform_params.longitude = 0
        waveform_params.polarization = 0
        waveform_params.spin1x = 0
        waveform_params.spin1y = 0
        waveform_params.spin1z = 0
        waveform_params.spin2x = 0
        waveform_params.spin2y = 0
        waveform_params.spin2z = 0
        # try:
        if True:
            if verbose:
                print(".. generating signal waveform ")
            tmplt_htilde, _params = get_waveform(tmplt_approx,
                                                 -1, -1, -1,
                                                 waveform_params,
                                                 f_lower,
                                                 1./delta_t,
                                                 filter_N,
                                                 datafile=tmplt_file)
            print(".. generated signal waveform ")
            m1, m2, w_value, _ = _params
            waveform_params.mass1 = m1
            waveform_params.mass2 = m2
            tmplt_h = make_frequency_series(tmplt_htilde)
            tmplt_h = extend_waveform_FrequencySeries(tmplt_h, filter_n)
        # except: raise IOError("Approximant %s not found.." % tmplt_approx)
    else:
        raise IOError("Template Approximant %s not found.." % tmplt_approx)
    #
    if aligned_spin_tmplt_only:
        _m1, _m2, _s1x, _s1y, _s1z, _s2x, _s2y, _s2z = m1, m2, 0, 0, s1z, 0, 0, s2z
    elif non_spin_tmplt_only:
        _m1, _m2, _s1x, _s1y, _s1z, _s2x, _s2y, _s2z = m1, m2, 0, 0, 0, 0, 0, 0
    else:
        _m1, _m2, _s1x, _s1y, _s1z, _s2x, _s2y, _s2z = m1, m2, s1x, s1y, s1z, s2x, s2y, s2z
    #
    # template = generator.generate_from_args(_m1, _m2, _s1x, _s1y, _s1z, _s2x, _s2y, _s2z,\
    #                              phic, tc, ra, dec, polarization)
    #
    if verbose:
        print(
            "..Generating template with masses = %3f, %.3f, spin1 = (%.3f, %.3f, %.3f), and  spin2 = (%.3f, %.3f, %.3f)" %
            (_m1, _m2, _s1x, _s1y, _s1z, _s2x, _s2y, _s2z))
        sys.stdout.flush()

    if tmplt_approx in pywf.fd_approximants():
        try:
            template = generator.generate_from_args(_m1, _m2, _s1x, _s1y, _s1z, _s2x, _s2y, _s2z,
                                                    phic, tc, ra, dec, polarization)
        except RuntimeError as rerr:
            print("""FAILED TO GENERATE %s waveform for
              masses = %.3f, %.3f
              spins = (%.3f, %.3f, %.3f), (%.3f, %.3f, %.3f)
              phic, tc, ra, dec, pol = (%.3f, %.3f, %.3f, %.3f, %.3f)""" %
                  (tmplt_approx, _m1, _m2, _s1x, _s1y, _s1z, _s2x, _s2y, _s2z,
                   phic, tc, ra, dec, polarization))
            raise RuntimeError(rerr)
        # NOTE: SEOBNRv4 has extra high frequency content, it seems..
        if 'SEOBNRv4_ROM' in tmplt_approx or 'SEOBNRv2_ROM' in tmplt_approx:
            template_h = extend_waveform_FrequencySeries(
                template['H1'], filter_n, force_fit=True)
        else:
            template_h = extend_waveform_FrequencySeries(
                template['H1'], filter_n)
    elif tmplt_approx in pywf.td_approximants():
        try:
            template = generator.generate_from_args(_m1, _m2, _s1x, _s1y, _s1z, _s2x, _s2y, _s2z,
                                                    phic, tc, ra, dec, polarization)
        except RuntimeError as rerr:
            print("""FAILED TO GENERATE %s waveform for
              masses = %.3f, %.3f
              spins = (%.3f, %.3f, %.3f), (%.3f, %.3f, %.3f)
              phic, tc, ra, dec, pol = (%.3f, %.3f, %.3f, %.3f, %.3f)""" %
                  (tmplt_approx, _m1, _m2, _s1x, _s1y, _s1z, _s2x, _s2y, _s2z,
                   phic, tc, ra, dec, polarization))
            raise RuntimeError(rerr)
        template_h = make_frequency_series(template['H1'])
        template_h = extend_waveform_FrequencySeries(template_h, filter_n)
    elif 'FromDataFile' in tmplt_approx:
        pass
    else:
        raise IOError("Template Approximant %s not found.." % tmplt_approx)

    # 4) COMPUTE MATCH
    m, idx = match(signal_h, template_h, psd=psd, low_frequency_cutoff=f_lower)

    if debug:
        print(
            "MATCH IS %.6f for parameters" % m, m1, m2, _s1x, _s1y, _s1z, _s2x, _s2y, _s2z)
        sys.stderr.flush()
    #
    # 5) RETURN OPTIMIZED MATCH
    return m, idx
Beispiel #12
0
def calculate_fitting_factor(m1, m2,
                             s1x=0, s1y=0, s1z=0,
                             s2x=0, s2y=0, s2z=0,
                             tc=0, phic=0,
                             ra=0, dec=0, polarization=0,
                             signal_approx='IMRPhenomD',
                             signal_file=None,
                             tmplt_approx='IMRPhenomC',
                             vary_masses_only=True,
                             vary_masses_and_aligned_spin_only=False,
                             chirp_mass_window=0.1,
                             effective_spin_window=0.5,
                             num_retries=4,
                             f_lower=15.0,
                             sample_rate=4096,
                             signal_duration=256,
                             psd_string='aLIGOZeroDetHighPower',
                             pso_swarm_size=500,
                             pso_omega=0.5,
                             pso_phip=0.5,
                             pso_phig=0.25,
                             pso_minfunc=1e-8,
                             verbose=True,
                             debug=False):
    """
Calculates the fitting factor for a signal of given physical
parameters, as modelled by a given signal approximant, against
templates of another approximant.

This function uses a particle swarm optimization to maximize
the overlaps between signal and templates. Algorithm parameters
are tunable, depending on how many dimensions we are optimizing
over.

IN PROGRESS: Adding facility to use "FromDataFile" waveforms
    """
    # {{{
    # 0) OPTION CHECKING
    if vary_masses_only:
        print("WARNING: Only component masses are allowed to be varied in templates. Setting the rest to signal values.")
    if vary_masses_and_aligned_spin_only:
        print("WARNING: Only component masses and spin components parallel to L allowed to be varied in templates. Setting the rest to signal values.")
    if vary_masses_only and vary_masses_and_aligned_spin_only:
        raise IOError(
            "Inconsistent options: vary_masses_only and vary_masses_and_aligned_spin_only")
    if (not vary_masses_only) and (not vary_masses_and_aligned_spin_only):
        print("WARNING: All mass and spin components varied in templates. Sky parameters still fixed to signal values.")

    # 1) GENERATE FILTERING META-PARAMETERS
    signal_duration = int(signal_duration)
    sample_rate = int(sample_rate)
    filter_N = signal_duration * sample_rate
    filter_n = filter_N / 2 + 1
    delta_t = 1./sample_rate
    delta_f = 1./signal_duration
    if verbose:
        print("signal_duration = %d, sample_rate = %d, filter_N = %d, filter_n = %d" % (
            signal_duration, sample_rate, filter_N, filter_n))
        print("deltaT = %f, deltaF = %f" % (delta_t, delta_f))
    # LIGO Noise PSD
    psd = from_string(psd_string, filter_n, delta_f, f_lower)

    # 2) GENERATE THE TARGET SIGNAL
    # PREPARATORY: Get the signal generator
    if signal_approx in pywf.fd_approximants():
        generator = pywfg.FDomainDetFrameGenerator(pywfg.FDomainCBCGenerator, 0,
                                                   variable_args=['mass1', 'mass2',
                                                                  'spin1x', 'spin1y', 'spin1z',
                                                                  'spin2x', 'spin2y', 'spin2z',
                                                                  'coa_phase',
                                                                  'tc', 'ra', 'dec', 'polarization'],
                                                   detectors=['H1'],
                                                   delta_f=delta_f, f_lower=f_lower,
                                                   approximant=signal_approx)
    elif signal_approx in pywf.td_approximants():
        generator = pywfg.TDomainDetFrameGenerator(pywfg.TDomainCBCGenerator, 0,
                                                   variable_args=['mass1', 'mass2',
                                                                  'spin1x', 'spin1y', 'spin1z',
                                                                  'spin2x', 'spin2y', 'spin2z',
                                                                  'coa_phase',
                                                                  'tc', 'ra', 'dec', 'polarization'],
                                                   detectors=['H1'],
                                                   delta_t=delta_t, f_lower=f_lower,
                                                   approximant=signal_approx)
    elif 'FromDataFile' in signal_approx:
        if os.path.getsize(signal_file) == 0:
            raise RuntimeError(
                " ERROR:...OOPS. Waveform file %s empty!!" % signal_file)
        try:
            _ = np.loadtxt(signal_file)
        except:
            raise RuntimeError(
                " WARNING: FAILURE READING DATA FROM %s.." % signal_file)

        waveform_params = lsctables.SimInspiral()
        waveform_params.latitude = 0
        waveform_params.longitude = 0
        waveform_params.polarization = 0
        waveform_params.spin1x = 0
        waveform_params.spin1y = 0
        waveform_params.spin1z = 0
        waveform_params.spin2x = 0
        waveform_params.spin2y = 0
        waveform_params.spin2z = 0
        # try:
        if True:
            if verbose:
                print(".. generating signal waveform ")
            signal_htilde, _params = get_waveform(signal_approx,
                                                  -1, -1, -1,
                                                  waveform_params,
                                                  f_lower,
                                                  sample_rate,
                                                  filter_N,
                                                  datafile=signal_file)
            print(".. generated signal waveform ")
            m1, m2, w_value, _ = _params
            waveform_params.mass1 = m1
            waveform_params.mass2 = m2
            signal_h = make_frequency_series(signal_htilde)
            signal_h = extend_waveform_FrequencySeries(signal_h, filter_n)
        # except: raise IOError("Approximant %s not found.." % signal_approx)
    else:
        raise IOError("Approximant %s not found.." % signal_approx)

    if verbose:
        print(
            "\nGenerating signal with masses = %3f, %.3f, spin1 = (%.3f, %.3f, %.3f), and  spin2 = (%.3f, %.3f, %.3f)" %
            (m1, m2, s1x, s1y, s1z, s2x, s2y, s2z))
        sys.stdout.flush()

    # Actually GENERATE THE SIGNAL
    if signal_approx in pywf.fd_approximants():
        signal = generator.generate_from_args(m1, m2, s1x, s1y, s1z, s2x, s2y, s2z,
                                              phic, tc, ra, dec, polarization)
        signal_h = extend_waveform_FrequencySeries(signal['H1'], filter_n)
    elif signal_approx in pywf.td_approximants():
        signal = generator.generate_from_args(m1, m2, s1x, s1y, s1z, s2x, s2y, s2z,
                                              phic, tc, ra, dec, polarization)
        signal_h = make_frequency_series(signal['H1'])
        signal_h = extend_waveform_FrequencySeries(signal_h, filter_n)
    elif 'FromDataFile' in signal_approx:
        pass
    else:
        raise IOError("Approximant %s not found.." % signal_approx)

    ###
    # NOW : Set up PSO calculation of the optimal overlap parameter set, i.e. \theta(FF)
    ###

    # 3) INITIALIZE THE WAVEFORM GENERATOR FOR TEMPLATES
    # We allow all intrinsic parameters to vary, and fix them to the signal
    # values, in case only masses or only mass+aligned-spin components are
    # requested to be varied. This fixing is done inside the objective function.
    if tmplt_approx in pywf.fd_approximants():
        generator_tmplt = pywfg.FDomainDetFrameGenerator(pywfg.FDomainCBCGenerator, 0,
                                                         variable_args=['mass1', 'mass2',
                                                                        'spin1x', 'spin1y', 'spin1z',
                                                                        'spin2x', 'spin2y', 'spin2z'
                                                                        ],
                                                         detectors=['H1'],
                                                         coa_phase=phic,
                                                         tc=tc, ra=ra, dec=dec, polarization=polarization,
                                                         delta_f=delta_f, f_lower=f_lower,
                                                         approximant=tmplt_approx)
    elif tmplt_approx in pywf.td_approximants():
        raise IOError(
            "Time-domain templates not supported yet (TDomainDetFrameGenerator doesn't exist)")
        generator_tmplt = pywfg.TDomainDetFrameGenerator(pywfg.TDomainCBCGenerator, 0,
                                                         variable_args=['mass1', 'mass2',
                                                                        'spin1x', 'spin1y', 'spin1z',
                                                                        'spin2x', 'spin2y', 'spin2z'
                                                                        ],
                                                         detectors=['H1'],
                                                         coa_phase=phic,
                                                         tc=tc, ra=ra, dec=dec, polarization=polarization,
                                                         delta_t=delta_t, f_lower=f_lower,
                                                         approximant=tmplt_approx)
    elif 'FromDataFile' in tmplt_approx:
        raise RuntimeError(
            "Using **templates** from data files is not implemented yet")
    else:
        raise IOError("Approximant %s not found.." % tmplt_approx)

    # 4) DEFINE AN OBJECTIVE FUNCTION FOR PSO TO MINIMIZE
    def objective_function_fitting_factor(x, *args):
        """
        This function is to be minimized if the fitting factor is to be found
        """
        objective_function_fitting_factor.counter += 1
        # 1) OBTAIN THE TEMPLATE PARAMETERS FROM X. ASSUME THAT ONLY
        # THOSE ARE PASSED THAT ARE NEEDED BY THE GENERATOR
        if len(x) == 2:
            m1, m2 = x
            if vary_masses_only:
                _s1x = _s1y = _s1z = _s2x = _s2y = _s2z = 0
            else:
                _s1x, _s1y, _s1z = s1x, s1y, s1z
                _s2x, _s2y, _s2z = s2x, s2y, s2z
        elif len(x) == 4:
            m1, m2, _s1z, _s2z = x
            if vary_masses_and_aligned_spin_only:
                _s1x = _s1y = _s2x = _s2y = 0
            else:
                _s1x, _s1y = s1x, s1y
                _s2x, _s2y = s2x, s2y
        elif len(x) == 8:
            m1, m2, _s1x, _s1y, _s1z, _s2x, _s2y, _s2z = x
        else:
            raise IOError(
                "No of vars %d not supported (should be 2 or 4 or 8)" % len(x))

        # 2) CHECK FOR CONSISTENCY
        if (_s1x**2 + _s1y**2 + _s1z**2) > s_max or (_s2x**2 + _s2y**2 + _s2z**2) > s_max:
            return 1e99

        # 2) ASSUME THAT
        signal_h, tmplt_generator = args
        tmplt = tmplt_generator.generate_from_args(
            m1, m2, _s1x, _s1y, _s1z, _s2x, _s2y, _s2z)
        tmplt_h = make_frequency_series(tmplt['H1'])

        if debug:
            print("IN FF Objective-> for parameters:",  m1,
                  m2, _s1x, _s1y, _s1z, _s2x, _s2y, _s2z)
        if debug:
            print("IN FF Objective-> Length(tmplt) = %d, making it %d" %
                  (len(tmplt['H1']), filter_n))
        # NOTE: SEOBNRv4 has extra high frequency content, it seems..
        if 'SEOBNRv4_ROM' in tmplt_approx or 'SEOBNRv2_ROM' in tmplt_approx:
            tmplt_h = extend_waveform_FrequencySeries(
                tmplt_h, filter_n, force_fit=True)
        else:
            tmplt_h = extend_waveform_FrequencySeries(tmplt_h, filter_n)

        # 3) COMPUTE MATCH
        m, _ = match(signal_h, tmplt_h, psd=psd, low_frequency_cutoff=f_lower)

        if debug:
            print("MATCH IS %.6f for parameters:" %
                  m, m1, m2, _s1x, _s1y, _s1z, _s2x, _s2y, _s2z)

        retval = np.log10(1. - m)

        # We do not want PSO to go berserk, so we stop when FF = 0.999999
        if retval <= -6.0:
            retval = -6.0
        return retval
    objective_function_fitting_factor.counter = 0

    # 5) DEFINE A CONSTRAINT FUNCTION FOR PSO TO RESPECT
    def constraint_function_fitting_factor(x, *args):
        """
        This function implements constraints on the optimization of fitting
        factors:
        1) spin magnitudes on both holes should be <= 1

        """
        if len(x) == 2:
            m1, m2 = x
            s1x = s1y = s1z = s2x = s2y = s2z = 0
        elif len(x) == 4:
            m1, m2, s1z, s2z = x
            s1x = s1y = s2x = s2y = 0
        elif len(x) == 8:
            m1, m2, s1x, s1y, s1z, s2x, s2y, s2z = x
        # 1) Constraint on spin magnitudes
        s1_mag = (s1x**2 + s1y**2 + s1z**2)**0.5
        s2_mag = (s2x**2 + s2y**2 + s2z**2)**0.5
        ##
        if (s1_mag > s_max) or (s2_mag > s_max):
            return -1
        # 2) Constraint on effective spin
        s_eff = (s1z * m1 + s2z * m2) / (m1 + m2)
        ##
        if (s_eff > s_eff_max) or (s_eff < s_eff_min):
            return -1
        # FINALLY) DEFAULT
        return 1

    # 6) FINALLY, CALL THE PSO TO COMPUTE THE FITTING FACTOR
    # 6a) FIRST CONSTRUCT THE FIXED ARGUMENTS FOR THE PSO's OBJECTIVE FUNCTION
    pso_args = (signal_h, generator_tmplt)

    # 6b) NOW SET THE RANGE OF PARAMETERS TO BE PROBED
    mt = m1 + m2 * 1.0
    et = m1 * m2 / mt / mt
    mc = mt * et**0.6
    mc_min = mc * (1.0 - chirp_mass_window)
    mc_max = mc * (1.0 + chirp_mass_window)
    et_max = 0.25
    et_min = 10. / 121.  # Lets say we trust waveform models up to q = 10
    m1_max, _ = pnutils.mchirp_eta_to_mass1_mass2(mc_max, et_min)
    m1_min, _ = pnutils.mchirp_eta_to_mass1_mass2(mc_min, et_max)
    _,      m2_max = pnutils.mchirp_eta_to_mass1_mass2(mc_max, et_max)
    _,      m2_min = pnutils.mchirp_eta_to_mass1_mass2(mc_min, et_min)
    s_min = -0.99
    s_max = +0.99
    s_eff = (s1z * m1 + s2z * m2) / (m1 + m2)
    s_eff_min = s_eff - effective_spin_window
    s_eff_max = s_eff + effective_spin_window

    if verbose:
        print(m1, m2, mt, et, mc, mc_min, mc_max, et_min,
              et_max, m1_min, m1_max, m2_min, m2_max)

    if vary_masses_only:
        low_lim = [m1_min, m2_min]
        high_lim = [m1_max, m2_max]
    elif vary_masses_and_aligned_spin_only:
        low_lim = [m1_min, m2_min, s_min, s_min]
        high_lim = [m1_max, m2_max, s_max, s_max]
    else:
        low_lim = [m1_min, m2_min, s_min, s_min, s_min, s_min, s_min, s_min]
        high_lim = [m1_max, m2_max, s_max, s_max, s_max, s_max, s_max, s_max]
    #
    if verbose:
        print("\nSearching within limits:\n", low_lim, " and \n", high_lim)
        print("\nCalculating overlap now..")
        sys.stdout.flush()
    olap, idx = calculate_faithfulness(m1, m2, s1x, s1y, s1z, s2x, s2y, s2z,
                                       tc=tc, phic=phic,
                                       ra=ra, dec=dec,
                                       polarization=polarization,
                                       signal_approx=signal_approx,
                                       signal_file=signal_file,
                                       tmplt_approx=tmplt_approx,
                                       tmplt_file=None,
                                       aligned_spin_tmplt_only=vary_masses_and_aligned_spin_only,
                                       non_spin_tmplt_only=vary_masses_only,
                                       f_lower=f_lower, sample_rate=sample_rate,
                                       signal_duration=signal_duration,
                                       verbose=verbose, debug=debug)
    #
    if verbose:
        print("Overlap with aligned_spin_tmplt_only = ", vary_masses_and_aligned_spin_only,
              " and non_spin_tmplt_only = ", vary_masses_only, ": ", olap, np.log10(
                  1. - olap))
        sys.stdout.flush()
    #
    idx = 1
    ff = 0.0
    while ff < olap:
        if idx and idx % 2 == 0:
            pso_minfunc *= 0.1
            pso_phig *= 1.1

        if idx > num_retries:
            print(
                "WARNING: Failed to improve on overlap in %d iterations. Set ff = olap now" % num_retries)
            ff = olap
            break

        if verbose:
            print("\nTry %d to compute fitting factor" % idx)
            sys.stdout.flush()
        params, ff = pso(objective_function_fitting_factor,
                         low_lim, high_lim,
                         f_ieqcons=constraint_function_fitting_factor,
                         args=pso_args,
                         swarmsize=pso_swarm_size,
                         omega=pso_omega,
                         phip=pso_phip,
                         phig=pso_phig,
                         minfunc=pso_minfunc,
                         maxiter=500,
                         debug=verbose)
        # Restore fitting factor from 1-ff
        ff = 1.0 - 10**ff
        if verbose:
            print("\nLoop will continue till %.12f < %.12f" % (ff, olap))
            sys.stdout.flush()
        idx += 1

    if verbose:
        print("optimization took %d objective func evals" %
              objective_function_fitting_factor.counter)
        sys.stdout.flush()
    #
    # 7) RETURN OPTIMIZED PARAMETERS
    return [params, olap, ff]
Beispiel #13
0
def align_waveforms_suboptimally(hplus1,
                                 hcross1,
                                 hplus2,
                                 hcross2,
                                 psd='aLIGOZeroDetHighPower',
                                 low_frequency_cutoff=None,
                                 high_frequency_cutoff=None,
                                 tsign=1,
                                 phsign=1,
                                 verify=True,
                                 trim_leading=False,
                                 trim_trailing=False,
                                 verbose=False):
    # Cast into time-series
    h_plus1 = TimeSeries(hplus1,
                         epoch=hplus1._epoch,
                         delta_t=hplus1.delta_t,
                         dtype=hplus1.dtype)
    h_cross1 = TimeSeries(hcross1,
                          epoch=hplus1._epoch,
                          delta_t=hplus1.delta_t,
                          dtype=hplus1.dtype)
    h_plus2 = TimeSeries(hplus2,
                         epoch=hplus2._epoch,
                         delta_t=hplus2.delta_t,
                         dtype=hplus2.dtype)
    h_cross2 = TimeSeries(hcross2,
                          epoch=hplus2._epoch,
                          delta_t=hplus2.delta_t,
                          dtype=hplus2.dtype)
    #
    # Ensure both input hplus vectors are equal in length
    if len(hplus2) > len(hplus1):
        h_plus1.append_zeros(len(hplus2) - len(hplus1))
        h_cross1.append_zeros(len(hplus2) - len(hplus1))
    elif len(hplus2) < len(hplus1):
        h_plus2.append_zeros(len(hplus1) - len(hplus2))
        h_cross2.append_zeros(len(hplus1) - len(hplus2))
    #
    htilde = make_frequency_series(h_plus1)
    stilde = make_frequency_series(h_plus2)
    #
    if high_frequency_cutoff == None:
        high_frequency_cutoff = 1. / h_plus1.delta_t / 2.
    #
    if psd == None:
        raise IOError("Need compatible psd [or name] as input!")
    elif type(psd) == str:
        psd_name = psd
        psd = from_string(psd_name, len(htilde), htilde.delta_f,
                          low_frequency_cutoff)
    #
    # Determine the phase and time shifts for optimal match
    snr, corr, snr_norm = matched_filter_core(
        htilde,
        stilde,
        # h_plus1, h_plus2,
        psd,
        low_frequency_cutoff,
        high_frequency_cutoff,
        None)
    max_snr, max_id = snr.abs_max_loc()

    if max_id != 0:
        t_shift = snr.delta_t * (len(snr) - max_id)
    else:
        t_shift = snr.delta_t * max_id

    ph_shift = np.angle(snr[max_id]) - 0.24850315030 - 0.0465881735639
    #
    if verbose:
        print(("max_id = %d, id_shift = %d" %
               (max_id, int(t_shift / snr.delta_t))))
        print(("t_shift = %f,\n ph_shift = %f" % (t_shift, ph_shift)))
    #
    # print(OVERLAPS
    if verbose:
        print(("Overlap BEFORE ALIGNMENT:",
               overlap_cplx(h_plus1,
                            h_plus2,
                            psd=psd,
                            low_frequency_cutoff=low_frequency_cutoff,
                            high_frequency_cutoff=high_frequency_cutoff,
                            normalized=True)))
        print(("Match BEFORE ALIGNMENT:",
               match(h_plus1,
                     h_plus2,
                     psd=psd,
                     low_frequency_cutoff=low_frequency_cutoff,
                     high_frequency_cutoff=high_frequency_cutoff)))

    # Shift whichever needs to be shifted to future time.
    # Shifting back in time is tricky.
    if t_shift >= 0:
        hp2, hc2 = shift_waveform_phase_time(h_plus2,
                                             h_cross2,
                                             tsign * t_shift,
                                             phsign * ph_shift,
                                             verbose=verbose)
    else:
        hp2, hc2 = shift_waveform_phase_time(h_plus2,
                                             h_cross2,
                                             tsign * t_shift,
                                             phsign * ph_shift,
                                             verbose=verbose)
    #
    # Ensure both input hplus vectors are equal in length
    if len(h_plus1) > len(hp2):
        hp2.append_zeros(len(h_plus1) - len(hp2))
    elif len(h_plus1) < len(hp2):
        h_plus1.append_zeros(len(hp2) - len(h_plus1))

    if verbose:
        htilde = make_frequency_series(h_plus1)
        psd = from_string(psd_name, len(htilde), htilde.delta_f,
                          low_frequency_cutoff)
        print(("Overlap AFTER ALIGNMENT:",
               overlap_cplx(h_plus1,
                            hp2,
                            psd=psd,
                            low_frequency_cutoff=low_frequency_cutoff,
                            high_frequency_cutoff=high_frequency_cutoff,
                            normalized=True)))
        print(("Match AFTER ALIGNMENT:",
               match(h_plus1,
                     hp2,
                     psd=psd,
                     low_frequency_cutoff=low_frequency_cutoff,
                     high_frequency_cutoff=high_frequency_cutoff)))
    if verify:
        #
        print("Verifying time alignment...")
        # Determine the phase and time shifts for optimal match
        snr, corr, snr_norm = matched_filter_core(  # htilde, stilde,
            h_plus1, hp2, psd, low_frequency_cutoff, high_frequency_cutoff,
            None)
        max_snr, max_id = snr.abs_max_loc()
        print(("Post-Alignment Index of MAX SNR (should be 0 or 1 or %d): %d" %
               (len(snr) - 1, max_id)))
        print(("Length of whole SNR time-series: ", len(snr)))
        if max_id != 0 and max_id != 1 and max_id != (
                len(snr) - 1) and max_id != (len(snr) - 2):
            # raise RuntimeError( "Warning: ALIGNMENT NOT CORRECT (see above)" )
            print("Warning: ALIGNMENT NOT CORRECT (see above)")
        else:
            print("Alignment in time correct..")
        #
        print("Verifying phase alignment...")
        ph_shift = np.angle(snr[max_id])
        if ph_shift != 0:
            print("Warning: Phasing alignment possibly incorrect.")
            print(("dphi, dphi+pi, dphi-pi: ", ph_shift, ph_shift + np.pi,
                   ph_shift - np.pi))
            print(("dphi/pi, dphi*pi: ", ph_shift / np.pi, ph_shift * np.pi))
        #

    #
    if trim_trailing:
        hp1 = trim_trailing_zeros(hp1)
        hc1 = trim_trailing_zeros(hc1)
        hp2 = trim_trailing_zeros(hp2)
        hc2 = trim_trailing_zeros(hc2)
    if trim_leading:
        hp1 = trim_leading_zeros(hp1)
        hc1 = trim_leading_zeros(hc1)
        hp2 = trim_leading_zeros(hp2)
        hc2 = trim_leading_zeros(hc2)
    #
    return hplus1, hcross1, hp2, hc2
Beispiel #14
0
def align_waveforms_optimally(hplus1,
                              hcross1,
                              hplus2,
                              hcross2,
                              psd='aLIGOZeroDetHighPower',
                              low_frequency_cutoff=None,
                              high_frequency_cutoff=None,
                              tsign=1,
                              phsign=-1,
                              verify=True,
                              phase_tolerance=1e-3,
                              overlap_tolerance=1e-3,
                              trim_leading=False,
                              trim_trailing=False,
                              verbose=False):
    """
    Align waveforms such that their inner product (noise weighted) is optimal
    without requiring any phase or time shift.

    The appropriate time and phase shifts are determined iteratively and applied
    to the second set of (hplus, hcross) vectors.
    """
    #############################################################################
    # First copy over data into local memory, ensure lengths of time and
    # frequency domain vectors are consistent, and compute the maximized overlap
    #
    # 1) Cast into time-series
    h_plus1 = TimeSeries(hplus1,
                         epoch=hplus1._epoch,
                         delta_t=hplus1.delta_t,
                         dtype=hplus1.dtype,
                         copy=True)
    h_cross1 = TimeSeries(hcross1,
                          epoch=hplus1._epoch,
                          delta_t=hplus1.delta_t,
                          dtype=hplus1.dtype,
                          copy=True)
    h_plus2 = TimeSeries(hplus2,
                         epoch=hplus2._epoch,
                         delta_t=hplus2.delta_t,
                         dtype=hplus2.dtype,
                         copy=True)
    h_cross2 = TimeSeries(hcross2,
                          epoch=hplus2._epoch,
                          delta_t=hplus2.delta_t,
                          dtype=hplus2.dtype,
                          copy=True)
    #
    # 2) Ensure both input hplus vectors are equal in length
    if len(hplus2) > len(hplus1):
        h_plus1.append_zeros(len(hplus2) - len(hplus1))
        h_cross1.append_zeros(len(hplus2) - len(hplus1))
    elif len(hplus2) < len(hplus1):
        h_plus2.append_zeros(len(hplus1) - len(hplus2))
        h_cross2.append_zeros(len(hplus1) - len(hplus2))
    #
    # 3) Set the upper frequency cutoff to Nyquist if not set by User
    if high_frequency_cutoff == None:
        high_frequency_cutoff = 1. / h_plus1.delta_t / 2.
    #
    # 4) Compute LIGO noise psd
    if psd == None:
        raise IOError("Need compatible psd [or name] as input!")
    elif type(psd) == str:
        htilde = make_frequency_series(h_plus1)
        psd_name = psd
        psd = from_string(psd_name, len(htilde), htilde.delta_f,
                          low_frequency_cutoff)
    ##
    # 5) Calculate Overlap (maximized) before alignment
    m = match(h_plus1,
              h_plus2,
              psd=psd,
              low_frequency_cutoff=low_frequency_cutoff,
              high_frequency_cutoff=high_frequency_cutoff)
    optimal_overlap = m[0]  # FIXME
    if verbose:
        print(("Overlap BEFORE ALIGNMENT:",
               overlap_cplx(h_plus1,
                            h_plus2,
                            psd=psd,
                            low_frequency_cutoff=low_frequency_cutoff,
                            high_frequency_cutoff=high_frequency_cutoff,
                            normalized=True)))
        print(("Match BEFORE ALIGNMENT:", m))
    #############################################################################
    # Iterate to obtain the correct phase and time shifts, using which we
    # align the two waveforms such that their unmaximized and maximized overlaps
    # agree.

    #
    # 1) Initialize phase/time offset counters
    t_shift_counter = 0
    ph_shift_counter = 0
    #
    # 2) Initialize initial garbage values to enter the while loop
    idx = 0
    ph_shift = t_shift = 1e9
    olap = 0 + 0j
    #
    # 3) Iteration begins
    # >>>>>>
    while np.abs(ph_shift) > phase_tolerance or \
            np.abs(t_shift) > h_plus1.delta_t or \
            np.abs(np.abs(olap.real) - optimal_overlap) > overlap_tolerance:
        if idx == 0:
            hp2, hc2 = h_plus2, h_cross2
        #
        # 1) Determine the phase and time shifts for optimal match
        #    by comparing hplus1/hcross1 with hp2/hc2 which is phase/time shifted
        #    in previous iteration
        snr, corr, snr_norm = matched_filter_core(h_plus1, hp2, psd,
                                                  low_frequency_cutoff,
                                                  high_frequency_cutoff, None)
        max_snr, max_id = snr.abs_max_loc()

        if max_id != 0:
            t_shift = snr.delta_t * (len(snr) - max_id)
        else:
            t_shift = snr.delta_t * max_id

        ph_shift = np.angle(snr[max_id])

        #
        # 2) Add them to running time/phase offset counter
        t_shift_counter += t_shift
        ph_shift_counter += ph_shift
        #
        if verbose:
            print((" >> Iteration %d\n" % (idx + 1)))
            print(("max_id = %d, id_shift = %d" %
                   (max_id, int(t_shift / snr.delta_t))))
            print(("t_shift = %f,\n ph_shift = %f" % (t_shift, ph_shift)))
        #
        ####
        # 3) Shift the second hp/hc pair (ORIGINAL) by cumulative phase/time offset
        hp2, hc2 = shift_waveform_phase_time(h_plus2,
                                             h_cross2,
                                             tsign * t_shift_counter,
                                             phsign * ph_shift_counter,
                                             verbose=verbose)
        #
        ###
        # 4) As time shifting can change array lengths, equalize again, compute psd
        ##
        if len(h_plus1) > len(hp2):
            hp2.append_zeros(len(h_plus1) - len(hp2))
            htilde = make_frequency_series(h_plus1)
            psd = from_string(psd_name, len(htilde), htilde.delta_f,
                              low_frequency_cutoff)
        elif len(h_plus1) < len(hp2):
            h_plus1.append_zeros(len(hp2) - len(h_plus1))
            htilde = make_frequency_series(h_plus1)
            psd = from_string(psd_name, len(htilde), htilde.delta_f,
                              low_frequency_cutoff)
        #
        # 5) Compute UNMAXIMIZED overlap.
        olap = overlap_cplx(h_plus1,
                            hp2,
                            psd=psd,
                            low_frequency_cutoff=low_frequency_cutoff,
                            high_frequency_cutoff=high_frequency_cutoff,
                            normalized=True)
        if verbose:
            print(("Overlap AFTER ALIGNMENT = ", olap))
            print(("Optimal Overlap = ", optimal_overlap))
        #
        idx += 1
        if verbose:
            print("\n")
    # >>>>>>
    # 3) Iteration ended.

    #############################################################################
    # Verify the alignment
    ###
    if verify:
        #
        print("Verifying time alignment...")
        #
        # 1) Determine the phase and time shifts for optimal match
        snr, corr, snr_norm = matched_filter_core(h_plus1, hp2, psd,
                                                  low_frequency_cutoff,
                                                  high_frequency_cutoff, None)
        max_snr, max_id = snr.abs_max_loc()
        if verbose:
            print(
                ("Post-Alignment Index of MAX SNR (should be 0 or 1 or %d): %d"
                 % (len(snr) - 1, max_id)))
            print(("Length of whole SNR time-series: ", len(snr)))
        #
        # 2) Test if current time shift is within tolerance
        if max_id != 0 and max_id != 1 and \
                max_id != (len(snr)-1) and max_id != (len(snr)-2):
            raise RuntimeError("Warning: ALIGNMENT NOT CORRECT (see above)")
        else:
            print("Alignment in time correct..")
        #
        # 3) Test if current phase shift is within tolerance
        print("Verifying phase alignment...")
        ph_shift = np.angle(snr[max_id])
        if np.abs(ph_shift) > phase_tolerance:
            if verbose:
                print(("dphi, dphi+pi, dphi-pi: ", ph_shift, ph_shift + np.pi,
                       ph_shift - np.pi))
                print(
                    ("dphi/pi, dphi*pi: ", ph_shift / np.pi, ph_shift * np.pi))
            raise RuntimeError(
                "Warning: Phasing alignment possibly incorrect.")
        else:
            if verbose:
                print(("Post-Alignmend Phase shift (should be < %.2e): %.2e" %
                       (phase_tolerance, np.abs(ph_shift))))
            print(("Alignment in phasing correct.. (within tol %.2e)" %
                   phase_tolerance))
        #

    #############################################################################
    # TRIM the output arrays and return
    if trim_trailing:
        hp2 = trim_trailing_zeros(hp2)
        hc2 = trim_trailing_zeros(hc2)
    if trim_leading:
        hp2 = trim_leading_zeros(hp2)
        hc2 = trim_leading_zeros(hc2)
    #
    return hplus1, hcross1, hp2, hc2
Beispiel #15
0
    def values(self, sn, indices, template, psd, norm, stilde=None,
               low_frequency_cutoff=None, high_frequency_cutoff=None):
        """
        Calculate the auto-chisq at the specified indices.

        Parameters
        -----------
        sn : Array[complex]
            SNR time series of the template for which auto-chisq is being
            computed. Provided unnormalized. 
        indices : Array[int]
            List of points at which to calculate auto-chisq
        template : Pycbc template object 
            The template for which we are calculating auto-chisq
        psd : Pycbc psd object
            The PSD of the data being analysed
        norm : float
            The normalization factor to apply to sn
        stilde : Pycbc data object, needed if using reverse-template
            The data being analysed. Only needed if using reverse-template,
            otherwise ignored
        low_frequency_cutoff : float
            The lower frequency to consider in matched-filters
        high_frequency_cutoff : float
            The upper frequency to consider in matched-filters
        """
        if self.do and (len(indices) > 0):
            htilde = make_frequency_series(template)

            # Check if we need to recompute the autocorrelation
            key = (id(template), id(psd))
            if key != self._autocor_id:
                logging.info("Calculating autocorrelation")

                if not self.reverse_template:
                    Pt, _Ptilde, P_norm = matched_filter_core(htilde,
                              htilde, psd=psd,
                              low_frequency_cutoff=low_frequency_cutoff,
                              high_frequency_cutoff=high_frequency_cutoff)
                    Pt = Pt * (1./ Pt[0])
                    self._autocor = Array(Pt, copy=True)
                else:
                    Pt, _Ptilde, P_norm = matched_filter_core(htilde,
                              htilde.conj(), psd=psd,
                              low_frequency_cutoff=low_frequency_cutoff,
                              high_frequency_cutoff=high_frequency_cutoff)

                    # T-reversed template has same norm as forward template
                    # so we can normalize using that
                    # FIXME: Here sigmasq has to be cast to a float or the
                    #        code is really slow ... why??
                    norm_fac = P_norm / float(((template.sigmasq(psd))**0.5))
                    Pt *= norm_fac
                    self._autocor = Array(Pt, copy=True)
                self._autocor_id = key
            
            logging.info("...Calculating autochisquare")
            sn = sn*norm
            if self.reverse_template:
                assert(stilde is not None)
                asn, acor, ahnrm = matched_filter_core(htilde.conj(), stilde,
                                 low_frequency_cutoff=low_frequency_cutoff,
                                 high_frequency_cutoff=high_frequency_cutoff,
                                 h_norm=template.sigmasq(psd))
                correlation_snr = asn * ahnrm
            else:
                correlation_snr = sn

            achi_list = np.array([])
            index_list = np.array(indices)
            dof, achi_list, _ = autochisq_from_precomputed(sn, correlation_snr,
                               self._autocor, index_list, stride=self.stride,
                               num_points=self.num_points,
                               oneside=self.one_sided, twophase=self.two_phase,
                               maxvalued=self.take_maximum_value)
            self.dof = dof
            return achi_list
Beispiel #16
0
    def values(self, sn, indices, template, psd, norm, stilde=None,
               low_frequency_cutoff=None, high_frequency_cutoff=None):
        """
        Calculate the auto-chisq at the specified indices.

        Parameters
        -----------
        sn : Array[complex]
            SNR time series of the template for which auto-chisq is being
            computed. Provided unnormalized. 
        indices : Array[int]
            List of points at which to calculate auto-chisq
        template : Pycbc template object 
            The template for which we are calculating auto-chisq
        psd : Pycbc psd object
            The PSD of the data being analysed
        norm : float
            The normalization factor to apply to sn
        stilde : Pycbc data object, needed if using reverse-template
            The data being analysed. Only needed if using reverse-template,
            otherwise ignored
        low_frequency_cutoff : float
            The lower frequency to consider in matched-filters
        high_frequency_cutoff : float
            The upper frequency to consider in matched-filters
        """
        if self.do and (len(indices) > 0):
            htilde = make_frequency_series(template)

            # Check if we need to recompute the autocorrelation
            key = (id(template), id(psd))
            if key != self._autocor_id:
                logging.info("Calculating autocorrelation")

                if not self.reverse_template:
                    Pt, _Ptilde, P_norm = matched_filter_core(htilde,
                              htilde, psd=psd,
                              low_frequency_cutoff=low_frequency_cutoff,
                              high_frequency_cutoff=high_frequency_cutoff)
                    Pt = Pt * (1./ Pt[0])
                    self._autocor = Array(Pt, copy=True)
                else:
                    Pt, _Ptilde, P_norm = matched_filter_core(htilde.conj(),
                              htilde, psd=psd,
                              low_frequency_cutoff=low_frequency_cutoff,
                              high_frequency_cutoff=high_frequency_cutoff)

                    # T-reversed template has same norm as forward template
                    # so we can normalize using that
                    # FIXME: Here sigmasq has to be cast to a float or the
                    #        code is really slow ... why??
                    norm_fac = P_norm / float(((template.sigmasq(psd))**0.5))
                    Pt *= norm_fac
                    self._autocor = Array(Pt, copy=True)
                self._autocor_id = key
            
            logging.info("...Calculating autochisquare")
            sn = sn*norm
            if self.reverse_template:
                assert(stilde is not None)
                asn, acor, ahnrm = matched_filter_core(htilde.conj(), stilde,
                                 low_frequency_cutoff=low_frequency_cutoff,
                                 high_frequency_cutoff=high_frequency_cutoff,
                                 h_norm=template.sigmasq(psd))
                correlation_snr = asn * ahnrm
            else:
                correlation_snr = sn

            achi_list = np.array([])
            index_list = np.array(indices)
            dof, achi_list, _ = autochisq_from_precomputed(sn, correlation_snr,
                               self._autocor, index_list, stride=self.stride,
                               num_points=self.num_points,
                               oneside=self.one_sided, twophase=self.two_phase,
                               maxvalued=self.take_maximum_value)
            self.dof = dof
            return achi_list
Beispiel #17
0
    def objective_function_fitting_factor(x, *args):
        """
        This function is to be minimized if the fitting factor is to be found
        """
        objective_function_fitting_factor.counter += 1
        # 1) OBTAIN THE TEMPLATE PARAMETERS FROM X. ASSUME THAT ONLY
        # THOSE ARE PASSED THAT ARE NEEDED BY THE GENERATOR
        if len(x) == 2:
            m1, m2 = x
            if vary_masses_only:
                _s1x = _s1y = _s1z = _s2x = _s2y = _s2z = 0
            else:
                _s1x, _s1y, _s1z = s1x, s1y, s1z
                _s2x, _s2y, _s2z = s2x, s2y, s2z
        elif len(x) == 4:
            m1, m2, _s1z, _s2z = x
            if vary_masses_and_aligned_spin_only:
                _s1x = _s1y = _s2x = _s2y = 0
            else:
                _s1x, _s1y = s1x, s1y
                _s2x, _s2y = s2x, s2y
        elif len(x) == 8:
            m1, m2, _s1x, _s1y, _s1z, _s2x, _s2y, _s2z = x
        else:
            raise IOError(
                "No of vars %d not supported (should be 2 or 4 or 8)" % len(x))

        # 2) CHECK FOR CONSISTENCY
        if (_s1x**2 + _s1y**2 + _s1z**2) > s_max or (_s2x**2 + _s2y**2 + _s2z**2) > s_max:
            return 1e99

        # 2) ASSUME THAT
        signal_h, tmplt_generator = args
        tmplt = tmplt_generator.generate_from_args(
            m1, m2, _s1x, _s1y, _s1z, _s2x, _s2y, _s2z)
        tmplt_h = make_frequency_series(tmplt['H1'])

        if debug:
            print("IN FF Objective-> for parameters:",  m1,
                  m2, _s1x, _s1y, _s1z, _s2x, _s2y, _s2z)
        if debug:
            print("IN FF Objective-> Length(tmplt) = %d, making it %d" %
                  (len(tmplt['H1']), filter_n))
        # NOTE: SEOBNRv4 has extra high frequency content, it seems..
        if 'SEOBNRv4_ROM' in tmplt_approx or 'SEOBNRv2_ROM' in tmplt_approx:
            tmplt_h = extend_waveform_FrequencySeries(
                tmplt_h, filter_n, force_fit=True)
        else:
            tmplt_h = extend_waveform_FrequencySeries(tmplt_h, filter_n)

        # 3) COMPUTE MATCH
        m, _ = match(signal_h, tmplt_h, psd=psd, low_frequency_cutoff=f_lower)

        if debug:
            print("MATCH IS %.6f for parameters:" %
                  m, m1, m2, _s1x, _s1y, _s1z, _s2x, _s2y, _s2z)

        retval = np.log10(1. - m)

        # We do not want PSO to go berserk, so we stop when FF = 0.999999
        if retval <= -6.0:
            retval = -6.0
        return retval
Beispiel #18
0
def get_waveform(wav, approximant, f_min, dt, N):
    """This function will generate the waveform corresponding to the point
    taken as input"""
    #{{{
    m1 = wav.mass1
    m2 = wav.mass2

    s1x = wav.spin1x
    s1y = wav.spin1y
    s1z = wav.spin1z
    s2x = wav.spin2x
    s2y = wav.spin2y
    s2z = wav.spin2z

    ecc = wav.alpha
    mean_per_ano = wav.alpha1
    long_asc_nodes = wav.alpha2
    coa_phase = wav.coa_phase

    inc = wav.inclination
    dist = wav.distance

    df = 1. / (dt * N)
    f_max = min(1. / (2. * dt), 0.15 / ((m1 + m2) * lal.MTSUN_SI))

    if approximant in fd_approximants():
        try:
            hptild, hctild = get_fd_waveform(approximant=approximant,
                                             mass1=m1,
                                             mass2=m2,
                                             spin1x=s1x,
                                             spin1y=s1y,
                                             spin1z=s1z,
                                             spin2x=s2x,
                                             spin2y=s2y,
                                             spin2z=s2z,
                                             eccentricity=ecc,
                                             mean_per_ano=mean_per_ano,
                                             long_asc_nodes=long_asc_nodes,
                                             coa_phase=coa_phase,
                                             inclination=inc,
                                             distance=dist,
                                             f_lower=f_min,
                                             f_final=f_max,
                                             delta_f=df)
        except RuntimeError as re:
            for c in dir(wav):
                if "__" not in c and "get" not in c and "set" not in c and hasattr(
                        wav, c):
                    print(c, getattr(wav, c))
            raise RuntimeError(re)
        hptilde = FrequencySeries(hptild,
                                  delta_f=df,
                                  dtype=np.complex128,
                                  copy=True)
        hpref_padded = FrequencySeries(zeros(N / 2 + 1),
                                       delta_f=df,
                                       dtype=np.complex128,
                                       copy=True)
        hpref_padded[0:len(hptilde)] = hptilde
        hctilde = FrequencySeries(hctild,
                                  delta_f=df,
                                  dtype=np.complex128,
                                  copy=True)
        hcref_padded = FrequencySeries(zeros(N / 2 + 1),
                                       delta_f=df,
                                       dtype=np.complex128,
                                       copy=True)
        hcref_padded[0:len(hctilde)] = hctilde
        href_padded = generate_detector_strain(wav, hpref_padded, hcref_padded)
    elif approximant in td_approximants():
        #raise IOError("Time domain approximants not supported at the moment..")
        try:
            hp, hc = get_td_waveform(approximant=approximant,
                                     mass1=m1,
                                     mass2=m2,
                                     spin1x=s1x,
                                     spin1y=s1y,
                                     spin1z=s1z,
                                     spin2x=s2x,
                                     spin2y=s2y,
                                     spin2z=s2z,
                                     eccentricity=ecc,
                                     mean_per_ano=mean_per_ano,
                                     long_asc_nodes=long_asc_nodes,
                                     coa_phase=coa_phase,
                                     inclination=inc,
                                     distance=dist,
                                     f_lower=f_min,
                                     delta_t=dt)
        except RuntimeError as re:
            for c in dir(wav):
                if "__" not in c and "get" not in c and "set" not in c and hasattr(
                        wav, c):
                    print(c, getattr(wav, c))
            raise RuntimeError(re)
        hpref_padded = TimeSeries(zeros(N),
                                  delta_t=dt,
                                  dtype=hp.dtype,
                                  copy=True)
        hpref_padded[:len(hp)] = hp
        hcref_padded = TimeSeries(zeros(N),
                                  delta_t=dt,
                                  dtype=hc.dtype,
                                  copy=True)
        hcref_padded[:len(hc)] = hc
        href_padded_td = generate_detector_strain(wav, hpref_padded,
                                                  hcref_padded)
        href_padded = make_frequency_series(href_padded_td)
    return href_padded