def fd_sequence(taper_start=None, taper_end=None, **kwds): from pycbc.waveform import get_fd_waveform_sequence if 'approximant' in kwds: kwds.pop("approximant") hp, hc = get_fd_waveform_sequence(approximant="TaylorF2", **kwds) sam = kwds['sample_points'].numpy() flow = sam[0] fhigh = sam[-1] if taper_start: l, r = numpy.searchsorted(sam, [flow, flow + taper_start]) fval = sam[l:r] x = (fval - flow) / taper_start w = winl(x) hp._data[l:r] *= w hc._data[l:r] *= w if taper_end: l, r = numpy.searchsorted(sam, [fhigh - taper_end, fhigh]) fval = sam[l:r] x = (fval - fhigh + taper_end) / taper_end w = winr(x) hp._data[l:r] *= w hc._data[l:r] *= w return hp, hc
def _loglr(self): r"""Computes the log likelihood ratio, .. math:: \log \mathcal{L}(\Theta) = \sum_i \left<h_i(\Theta)|d_i\right> - \frac{1}{2}\left<h_i(\Theta)|h_i(\Theta)\right>, at the current parameter values :math:`\Theta`. Returns ------- float The value of the log likelihood ratio. """ # get model params p = self.current_params.copy() p.update(self.static_params) hh = 0.0 hd = 0j for ifo in self.data: # get detector antenna pattern fp, fc = self.det[ifo].antenna_pattern( p["ra"], p["dec"], p["polarization"], self.antenna_time[ifo] ) # get timeshift relative to end of data dt = self.det[ifo].time_delay_from_earth_center( p["ra"], p["dec"], p["tc"] ) dtc = p["tc"] + dt - self.end_time[ifo] tshift = numpy.exp(-2.0j * numpy.pi * self.fedges[ifo] * dtc) # generate template and calculate waveform ratio hp, hc = get_fd_waveform_sequence( sample_points=Array(self.fedges[ifo]), **p ) htilde = numpy.array(fp * hp + fc * hc) * tshift r = (htilde / self.h00_sparse[ifo]).astype(numpy.complex128) r0 = r[:-1] r1 = (r[1:] - r[:-1]) / ( self.fedges[ifo][1:] - self.fedges[ifo][:-1] ) # <h, d> is sum over bins of A0r0 + A1r1 hd += numpy.sum( self.sdat[ifo]["a0"] * r0 + self.sdat[ifo]["a1"] * r1 ) # <h, h> is sum over bins of B0|r0|^2 + 2B1Re(r1r0*) hh += numpy.sum( self.sdat[ifo]["b0"] * numpy.absolute(r0) ** 2.0 + 2.0 * self.sdat[ifo]["b1"] * (r1 * numpy.conjugate(r0)).real ) hd = abs(hd) llr = numpy.log(special.i0e(hd)) + hd - 0.5 * hh return float(llr)
def get_waveforms(self, params): """ Get the waveform polarizations for each ifo """ wfs = [] for edge in self.edge_unique: hp, hc = get_fd_waveform_sequence(sample_points=edge, **params) hp = hp.numpy() hc = hc.numpy() wfs.append((hp, hc)) return {ifo: wfs[self.ifo_map[ifo]] for ifo in self.data}
def __init__(self, variable_params, data, low_frequency_cutoff, fiducial_params=None, epsilon=0.5, **kwargs): super(Relative, self).__init__(variable_params, data, low_frequency_cutoff, **kwargs) # check that all of the frequency cutoffs are the same # FIXME: this can probably be loosened at some point kmins = list(self.kmin.values()) kmaxs = list(self.kmax.values()) if any(kk != kmins[0] for kk in kmins): raise ValueError("All lower frequency cutoffs must be the same") if any(kk != kmaxs[0] for kk in kmaxs): raise ValueError("All high frequency cutoffs must be the same") # store data and frequencies d0 = list(self.data.values())[0] self.f = numpy.array(d0.sample_frequencies) self.df = d0.delta_f self.end_time = float(d0.end_time) self.det = {ifo: Detector(ifo) for ifo in self.data} self.epsilon = float(epsilon) # store data and psds as arrays for faster computation self.comp_data = {ifo: d.numpy() for ifo, d in self.data.items()} self.comp_psds = {ifo: p.numpy() for ifo, p in self.psds.items()} # store fiducial waveform params self.fid_params = fiducial_params # get detector-specific arrival times relative to end of data dt = { ifo: self.det[ifo].time_delay_from_earth_center(self.fid_params['ra'], self.fid_params['dec'], self.fid_params['tc']) for ifo in self.data } self.ta = { ifo: self.fid_params['tc'] + dt[ifo] - self.end_time for ifo in self.data } # generate fiducial waveform f_lo = kmins[0] * self.df f_hi = kmaxs[0] * self.df logging.info("Generating fiducial waveform from %s to %s Hz", f_lo, f_hi) # prune low frequency samples to avoid waveform errors nbelow = sum(self.f < 10) fpoints = Array(self.f.astype(numpy.float64))[nbelow:] approx = self.static_params['approximant'] fid_hp, fid_hc = get_fd_waveform_sequence(approximant=approx, sample_points=fpoints, **self.fid_params) self.h00 = {} for ifo in self.data: # make copy of fiducial wfs, adding back in low frequencies hp0 = numpy.concatenate([[0j] * nbelow, fid_hp.copy()]) hc0 = numpy.concatenate([[0j] * nbelow, fid_hc.copy()]) fp, fc = self.det[ifo].antenna_pattern( self.fid_params['ra'], self.fid_params['dec'], self.fid_params['polarization'], self.fid_params['tc']) tshift = numpy.exp(-2.0j * numpy.pi * self.f * self.ta[ifo]) self.h00[ifo] = numpy.array(hp0 * fp + hc0 * fc) * tshift # compute frequency bins logging.info("Computing frequency bins") nbin, fbin, fbin_ind = setup_bins(f_full=self.f, f_lo=kmins[0] * self.df, f_hi=kmaxs[0] * self.df, eps=self.epsilon) logging.info("Using %s bins for this model", nbin) # store bins and edges in sample and frequency space self.edges = fbin_ind self.fedges = numpy.array(fbin).astype(numpy.float64) self.bins = numpy.array([(self.edges[i], self.edges[i + 1]) for i in range(len(self.edges) - 1)]) self.fbins = numpy.array([(fbin[i], fbin[i + 1]) for i in range(len(fbin) - 1)]) # store low res copy of fiducial waveform self.h00_sparse = { ifo: self.h00[ifo].copy().take(self.edges) for ifo in self.h00 } # compute summary data logging.info("Calculating summary data at frequency resolution %s Hz", self.df) self.sdat = self.summary_data()
def __init__(self, variable_params, data, low_frequency_cutoff, fiducial_params=None, gammas=None, epsilon=0.5, vary_polarization=False, **kwargs): super(Relative, self).__init__(variable_params, data, low_frequency_cutoff, **kwargs) # check that all of the frequency cutoffs are the same # FIXME: this can probably be loosened at some point kmins = list(self.kmin.values()) kmaxs = list(self.kmax.values()) if any(kk != kmins[0] for kk in kmins): raise ValueError("All lower frequency cutoffs must be the same") if any(kk != kmaxs[0] for kk in kmaxs): raise ValueError("All high frequency cutoffs must be the same") # store data and frequencies d0 = list(self.data.values())[0] self.f = numpy.array(d0.sample_frequencies) self.df = d0.delta_f self.end_time = float(d0.end_time) self.det = {ifo: Detector(ifo) for ifo in self.data} self.epsilon = float(epsilon) # store data and psds as arrays for faster computation self.comp_data = {ifo: d.numpy() for ifo, d in self.data.items()} self.comp_psds = {ifo: p.numpy() for ifo, p in self.psds.items()} # store fiducial waveform params self.fid_params = fiducial_params # get detector-specific arrival times relative to end of data dt = { ifo: self.det[ifo].time_delay_from_earth_center(self.fid_params['ra'], self.fid_params['dec'], self.fid_params['tc']) for ifo in self.data } self.ta = { ifo: self.fid_params['tc'] + dt[ifo] - self.end_time for ifo in self.data } # generate fiducial waveform f_lo = kmins[0] * self.df f_hi = kmaxs[0] * self.df logging.info("Generating fiducial waveform from %s to %s Hz", f_lo, f_hi) # prune low frequency samples to avoid waveform errors nbelow = sum(self.f < f_lo) fpoints = Array(self.f.astype(numpy.float64))[nbelow:] approx = self.static_params['approximant'] fid_hp, fid_hc = get_fd_waveform_sequence(approximant=approx, sample_points=fpoints, **self.fid_params) # check for zeros at high frequencies numzeros = list(fid_hp[::-1] != 0j).index(True) n_above_fhi = (len(self.f) - 1) - kmaxs[0] # make sure only nonzero samples are included in bins if numzeros > n_above_fhi: nremove = numzeros - n_above_fhi new_kmax = kmaxs[0] - nremove f_hi = new_kmax * self.df logging.info( "WARNING! Fiducial waveform terminates below " "high-frequency-cutoff, final bin frequency " "will be %s Hz", f_hi) self.h00 = {} for ifo in self.data: # make copy of fiducial wfs, adding back in low frequencies hp0 = numpy.concatenate([[0j] * nbelow, fid_hp.copy()]) hc0 = numpy.concatenate([[0j] * nbelow, fid_hc.copy()]) fp, fc = self.det[ifo].antenna_pattern( self.fid_params['ra'], self.fid_params['dec'], self.fid_params['polarization'], self.fid_params['tc']) tshift = numpy.exp(-2.0j * numpy.pi * self.f * self.ta[ifo]) self.h00[ifo] = numpy.array(hp0 * fp + hc0 * fc) * tshift # compute frequency bins logging.info("Computing frequency bins") nbin, fbin, fbin_ind = setup_bins(f_full=self.f, f_lo=f_lo, f_hi=f_hi, gammas=gammas, eps=self.epsilon) logging.info("Using %s bins for this model", nbin) # store bins and edges in sample and frequency space self.edges = fbin_ind self.fedges = numpy.array(fbin).astype(numpy.float64) self.bins = numpy.array([(self.edges[i], self.edges[i + 1]) for i in range(len(self.edges) - 1)]) self.fbins = numpy.array([(fbin[i], fbin[i + 1]) for i in range(len(fbin) - 1)]) # store low res copy of fiducial waveform self.h00_sparse = { ifo: self.h00[ifo].copy().take(self.edges) for ifo in self.h00 } # compute summary data logging.info("Calculating summary data at frequency resolution %s Hz", self.df) self.sdat = self.summary_data() # Calculate the times to evaluate fp/fc if vary_polarization is not False: logging.info('Enabling frequency-dependent polarization') from pycbc.waveform.spa_tmplt import spa_length_in_time times = spa_length_in_time(phase_order=-1, mass1=self.fid_params['mass1'], mass2=self.fid_params['mass2'], f_lower=self.fedges) self.antenna_time = self.fid_params['tc'] - times else: self.antenna_time = self.fid_params['tc']
def __init__( self, variable_params, data, low_frequency_cutoff, fiducial_params=None, gammas=None, epsilon=0.5, vary_polarization=False, **kwargs ): super(Relative, self).__init__( variable_params, data, low_frequency_cutoff, **kwargs ) self.epsilon = float(epsilon) # reference waveform and bin edges self.h00, self.h00_sparse = {}, {} self.f, self.df, self.end_time, self.det = {}, {}, {}, {} self.edges, self.fedges, self.bins, self.fbins = {}, {}, {}, {} self.ta = {} self.antenna_time = {} # filtered summary data for linear approximation self.sdat = {} # store data and psds as arrays for faster computation self.comp_data = {ifo: d.numpy() for ifo, d in self.data.items()} self.comp_psds = {ifo: p.numpy() for ifo, p in self.psds.items()} # store fiducial waveform params self.fid_params = fiducial_params for ifo in data: # store data and frequencies d0 = self.data[ifo] self.f[ifo] = numpy.array(d0.sample_frequencies) self.df[ifo] = d0.delta_f self.end_time[ifo] = float(d0.end_time) self.det[ifo] = Detector(ifo) # get detector-specific arrival times relative to end of data dt = self.det[ifo].time_delay_from_earth_center( self.fid_params["ra"], self.fid_params["dec"], self.fid_params["tc"], ) self.ta[ifo] = self.fid_params["tc"] + dt - self.end_time[ifo] # generate fiducial waveform f_lo = self.kmin[ifo] * self.df[ifo] f_hi = self.kmax[ifo] * self.df[ifo] logging.info( "%s: Generating fiducial waveform from %s to %s Hz", ifo, f_lo, f_hi, ) # prune low frequency samples to avoid waveform errors nbelow = sum(self.f[ifo] < f_lo) fpoints = Array(self.f[ifo].astype(numpy.float64))[nbelow:] approx = self.static_params["approximant"] fid_hp, fid_hc = get_fd_waveform_sequence( approximant=approx, sample_points=fpoints, **self.fid_params ) # check for zeros at high frequencies numzeros = list(fid_hp[::-1] != 0j).index(True) n_above_fhi = (len(self.f[ifo]) - 1) - self.kmax[ifo] # make sure only nonzero samples are included in bins if numzeros > n_above_fhi: nremove = numzeros - n_above_fhi new_kmax = self.kmax[ifo] - nremove f_hi = new_kmax * self.df[ifo] logging.info( "WARNING! Fiducial waveform terminates below " "high-frequency-cutoff, final bin frequency " "will be %s Hz", f_hi, ) # make copy of fiducial wfs, adding back in low frequencies hp0 = numpy.concatenate([[0j] * nbelow, fid_hp.copy()]) hc0 = numpy.concatenate([[0j] * nbelow, fid_hc.copy()]) fp, fc = self.det[ifo].antenna_pattern( self.fid_params["ra"], self.fid_params["dec"], self.fid_params["polarization"], self.fid_params["tc"], ) tshift = numpy.exp(-2.0j * numpy.pi * self.f[ifo] * self.ta[ifo]) self.h00[ifo] = numpy.array(hp0 * fp + hc0 * fc) * tshift # compute frequency bins logging.info("Computing frequency bins") nbin, fbin, fbin_ind = setup_bins( f_full=self.f[ifo], f_lo=f_lo, f_hi=f_hi, gammas=gammas, eps=self.epsilon, ) logging.info("Using %s bins for this model", nbin) # store bins and edges in sample and frequency space self.edges[ifo] = fbin_ind self.fedges[ifo] = numpy.array(fbin).astype(numpy.float64) self.bins[ifo] = numpy.array( [ (self.edges[ifo][i], self.edges[ifo][i + 1]) for i in range(len(self.edges[ifo]) - 1) ] ) self.fbins[ifo] = numpy.array( [(fbin[i], fbin[i + 1]) for i in range(len(fbin) - 1)] ) # store low res copy of fiducial waveform self.h00_sparse[ifo] = self.h00[ifo].copy().take(self.edges[ifo]) # compute summary data logging.info( "Calculating summary data at frequency resolution %s Hz", self.df[ifo], ) self.sdat[ifo] = self.summary_data(ifo) # Calculate the times to evaluate fp/fc if vary_polarization is not False: logging.info("Enabling frequency-dependent polarization") from pycbc.waveform.spa_tmplt import spa_length_in_time times = spa_length_in_time( phase_order=-1, mass1=self.fid_params["mass1"], mass2=self.fid_params["mass2"], f_lower=self.fedges[ifo], ) self.antenna_time[ifo] = self.fid_params["tc"] - times else: self.antenna_time[ifo] = self.fid_params["tc"]
def __init__(self, variable_params, data, low_frequency_cutoff, fiducial_params=None, gammas=None, epsilon=0.5, earth_rotation=False, marginalize_phase=True, **kwargs): variable_params, kwargs = self.setup_distance_marginalization( variable_params, marginalize_phase=marginalize_phase, **kwargs) super(Relative, self).__init__(variable_params, data, low_frequency_cutoff, **kwargs) self.epsilon = float(epsilon) # reference waveform and bin edges self.h00, self.h00_sparse = {}, {} self.f, self.df, self.end_time, self.det = {}, {}, {}, {} self.edges, self.fedges, self.bins, self.fbins = {}, {}, {}, {} self.ta = {} self.antenna_time = {} # filtered summary data for linear approximation self.sdat = {} # store data and psds as arrays for faster computation self.comp_data = {ifo: d.numpy() for ifo, d in self.data.items()} self.comp_psds = {ifo: p.numpy() for ifo, p in self.psds.items()} # store fiducial waveform params self.fid_params = self.static_params.copy() self.fid_params.update(fiducial_params) for ifo in data: # store data and frequencies d0 = self.data[ifo] self.f[ifo] = numpy.array(d0.sample_frequencies) self.df[ifo] = d0.delta_f self.end_time[ifo] = float(d0.end_time) self.det[ifo] = Detector(ifo) # get detector-specific arrival times relative to end of data dt = self.det[ifo].time_delay_from_earth_center( self.fid_params["ra"], self.fid_params["dec"], self.fid_params["tc"], ) self.ta[ifo] = self.fid_params["tc"] + dt - self.end_time[ifo] # generate fiducial waveform f_lo = self.kmin[ifo] * self.df[ifo] f_hi = self.kmax[ifo] * self.df[ifo] logging.info( "%s: Generating fiducial waveform from %s to %s Hz", ifo, f_lo, f_hi, ) # prune low frequency samples to avoid waveform errors fpoints = Array(self.f[ifo].astype(numpy.float64)) fpoints = fpoints[self.kmin[ifo]:self.kmax[ifo] + 1] fid_hp, fid_hc = get_fd_waveform_sequence(sample_points=fpoints, **self.fid_params) # check for zeros at high frequencies # make sure only nonzero samples are included in bins numzeros = list(fid_hp[::-1] != 0j).index(True) if numzeros > 0: new_kmax = self.kmax[ifo] - numzeros f_hi = new_kmax * self.df[ifo] logging.info( "WARNING! Fiducial waveform terminates below " "high-frequency-cutoff, final bin frequency " "will be %s Hz", f_hi) # make copy of fiducial wfs, adding back in low frequencies fid_hp.resize(len(self.f[ifo])) fid_hc.resize(len(self.f[ifo])) hp0 = numpy.roll(fid_hp, self.kmin[ifo]) hc0 = numpy.roll(fid_hc, self.kmin[ifo]) fp, fc = self.det[ifo].antenna_pattern( self.fid_params["ra"], self.fid_params["dec"], self.fid_params["polarization"], self.fid_params["tc"]) tshift = numpy.exp(-2.0j * numpy.pi * self.f[ifo] * self.ta[ifo]) self.h00[ifo] = numpy.array(hp0 * fp + hc0 * fc) * tshift # compute frequency bins logging.info("Computing frequency bins") nbin, fbin, fbin_ind = setup_bins( f_full=self.f[ifo], f_lo=f_lo, f_hi=f_hi, gammas=gammas, eps=self.epsilon, ) logging.info("Using %s bins for this model", nbin) # store bins and edges in sample and frequency space self.edges[ifo] = fbin_ind self.fedges[ifo] = numpy.array(fbin).astype(numpy.float64) self.bins[ifo] = numpy.array([ (self.edges[ifo][i], self.edges[ifo][i + 1]) for i in range(len(self.edges[ifo]) - 1) ]) self.fbins[ifo] = numpy.array([(fbin[i], fbin[i + 1]) for i in range(len(fbin) - 1)]) # store low res copy of fiducial waveform self.h00_sparse[ifo] = self.h00[ifo].copy().take(self.edges[ifo]) # compute summary data logging.info( "Calculating summary data at frequency resolution %s Hz", self.df[ifo], ) self.sdat[ifo] = self.summary_data(ifo) # Calculate the times to evaluate fp/fc if earth_rotation is not False: logging.info("Enabling frequency-dependent earth rotation") from pycbc.waveform.spa_tmplt import spa_length_in_time times = spa_length_in_time( phase_order=-1, mass1=self.fid_params["mass1"], mass2=self.fid_params["mass2"], f_lower=self.fedges[ifo], ) self.antenna_time[ifo] = self.fid_params["tc"] - times self.lik = likelihood_parts_v else: self.antenna_time[ifo] = self.fid_params["tc"] self.lik = likelihood_parts # determine the unique ifo layouts self.edge_unique = [] self.ifo_map = {} for ifo in self.fedges: if len(self.edge_unique) == 0: self.ifo_map[ifo] = 0 self.edge_unique.append(Array(self.fedges[ifo])) else: for i, edge in enumerate(self.edge_unique): if numpy.array_equal(edge, self.fedges[ifo]): self.ifo_map[ifo] = i break else: self.ifo_map[ifo] = len(self.edge_unique) self.edge_unique.append(Array(self.fedges[ifo])) logging.info("%s unique ifo layouts", len(self.edge_unique))
def __init__( self, variable_params, data, low_frequency_cutoff, fiducial_params=None, gammas=None, epsilon=0.5, earth_rotation=False, marginalize_phase=True, **kwargs ): variable_params, kwargs = self.setup_distance_marginalization( variable_params, marginalize_phase=marginalize_phase, **kwargs) super(Relative, self).__init__( variable_params, data, low_frequency_cutoff, **kwargs ) # reference waveform and bin edges self.f, self.df, self.end_time, self.det = {}, {}, {}, {} self.h00, self.h00_sparse = {}, {} self.fedges, self.edges = {}, {} self.antenna_time = {} # filtered summary data for linear approximation self.sdat = {} # store fiducial waveform params self.fid_params = self.static_params.copy() self.fid_params.update(fiducial_params) for k in self.static_params: if self.fid_params[k] == 'REPLACE': self.fid_params.pop(k) for ifo in data: # store data and frequencies d0 = self.data[ifo] self.f[ifo] = numpy.array(d0.sample_frequencies) self.df[ifo] = d0.delta_f self.end_time[ifo] = float(d0.end_time) self.det[ifo] = Detector(ifo) # generate fiducial waveform f_lo = self.kmin[ifo] * self.df[ifo] f_hi = self.kmax[ifo] * self.df[ifo] logging.info( "%s: Generating fiducial waveform from %s to %s Hz", ifo, f_lo, f_hi, ) # prune low frequency samples to avoid waveform errors fpoints = Array(self.f[ifo].astype(numpy.float64)) fpoints = fpoints[self.kmin[ifo]:self.kmax[ifo]+1] fid_hp, fid_hc = get_fd_waveform_sequence(sample_points=fpoints, **self.fid_params) # check for zeros at high frequencies # make sure only nonzero samples are included in bins numzeros = list(fid_hp[::-1] != 0j).index(True) if numzeros > 0: new_kmax = self.kmax[ifo] - numzeros f_hi = new_kmax * self.df[ifo] logging.info( "WARNING! Fiducial waveform terminates below " "high-frequency-cutoff, final bin frequency " "will be %s Hz", f_hi) # make copy of fiducial wfs, adding back in low frequencies fid_hp.resize(len(self.f[ifo])) fid_hc.resize(len(self.f[ifo])) hp0 = numpy.roll(fid_hp, self.kmin[ifo]) hc0 = numpy.roll(fid_hc, self.kmin[ifo]) # get detector-specific arrival times relative to end of data dt = self.det[ifo].time_delay_from_earth_center( self.fid_params["ra"], self.fid_params["dec"], self.fid_params["tc"], ) ta = self.fid_params["tc"] + dt - self.end_time[ifo] tshift = numpy.exp(-2.0j * numpy.pi * self.f[ifo] * ta) fp, fc = self.det[ifo].antenna_pattern( self.fid_params["ra"], self.fid_params["dec"], self.fid_params["polarization"], self.fid_params["tc"]) h00 = (hp0 * fp + hc0 * fc) * tshift self.h00[ifo] = h00 # compute frequency bins logging.info("Computing frequency bins") fbin_ind = setup_bins( f_full=self.f[ifo], f_lo=f_lo, f_hi=f_hi, gammas=gammas, eps=float(epsilon), ) logging.info("Using %s bins for this model", len(fbin_ind)) self.fedges[ifo] = self.f[ifo][fbin_ind] self.edges[ifo] = fbin_ind self.init_from_frequencies(h00, fbin_ind, ifo) self.antenna_time[ifo] = self.setup_antenna(earth_rotation, self.fedges[ifo]) self.combine_layout()