def test_varying_orbital_phase(self): #"""Check that the waveform is consistent under phase changes #""" if self.p.approximant in td_approximants(): sample_attr = 'sample_times' else: sample_attr = 'sample_frequencies' f = pylab.figure() pylab.axes([.1, .2, 0.8, 0.70]) hp_ref, hc_ref = get_waveform(self.p, coa_phase=0) pylab.plot(getattr(hp_ref, sample_attr), hp_ref.real(), label="phiref") hp, hc = get_waveform(self.p, coa_phase=lal.PI / 4) m, i = match(hp_ref, hp) self.assertAlmostEqual(1, m, places=2) o = overlap(hp_ref, hp) pylab.plot(getattr(hp, sample_attr), hp.real(), label="$phiref \pi/4$") hp, hc = get_waveform(self.p, coa_phase=lal.PI / 2) m, i = match(hp_ref, hp) o = overlap(hp_ref, hp) self.assertAlmostEqual(1, m, places=7) self.assertAlmostEqual(-1, o, places=7) pylab.plot(getattr(hp, sample_attr), hp.real(), label="$phiref \pi/2$") hp, hc = get_waveform(self.p, coa_phase=lal.PI) m, i = match(hp_ref, hp) o = overlap(hp_ref, hp) self.assertAlmostEqual(1, m, places=7) self.assertAlmostEqual(1, o, places=7) pylab.plot(getattr(hp, sample_attr), hp.real(), label="$phiref \pi$") pylab.xlim(min(getattr(hp, sample_attr)), max(getattr(hp, sample_attr))) pylab.title("Vary %s oribital phiref, h+" % self.p.approximant) if self.p.approximant in td_approximants(): pylab.xlabel("Time to coalescence (s)") else: pylab.xlabel("GW Frequency (Hz)") pylab.ylabel("GW Strain (real part)") pylab.legend(loc="upper left") info = self.version_txt pylab.figtext(0.05, 0.05, info) if self.save_plots: pname = self.plot_dir + "/%s-vary-phase.png" % self.p.approximant pylab.savefig(pname) if self.show_plots: pylab.show() else: pylab.close(f)
def test_varying_orbital_phase(self): #"""Check that the waveform is consistent under phase changes #""" if self.p.approximant in td_approximants(): sample_attr = 'sample_times' else: sample_attr = 'sample_frequencies' f = pylab.figure() pylab.axes([.1, .2, 0.8, 0.70]) hp_ref, hc_ref = get_waveform(self.p, coa_phase=0) pylab.plot(getattr(hp_ref, sample_attr), hp_ref.real(), label="phiref") hp, hc = get_waveform(self.p, coa_phase=lal.PI/4) m, i = match(hp_ref, hp) self.assertAlmostEqual(1, m, places=2) o = overlap(hp_ref, hp) pylab.plot(getattr(hp, sample_attr), hp.real(), label="$phiref \pi/4$") hp, hc = get_waveform(self.p, coa_phase=lal.PI/2) m, i = match(hp_ref, hp) o = overlap(hp_ref, hp) self.assertAlmostEqual(1, m, places=7) self.assertAlmostEqual(-1, o, places=7) pylab.plot(getattr(hp, sample_attr), hp.real(), label="$phiref \pi/2$") hp, hc = get_waveform(self.p, coa_phase=lal.PI) m, i = match(hp_ref, hp) o = overlap(hp_ref, hp) self.assertAlmostEqual(1, m, places=7) self.assertAlmostEqual(1, o, places=7) pylab.plot(getattr(hp, sample_attr), hp.real(), label="$phiref \pi$") pylab.xlim(min(getattr(hp, sample_attr)), max(getattr(hp, sample_attr))) pylab.title("Vary %s oribital phiref, h+" % self.p.approximant) if self.p.approximant in td_approximants(): pylab.xlabel("Time to coalescence (s)") else: pylab.xlabel("GW Frequency (Hz)") pylab.ylabel("GW Strain (real part)") pylab.legend(loc="upper left") info = self.version_txt pylab.figtext(0.05, 0.05, info) if self.save_plots: pname = self.plot_dir + "/%s-vary-phase.png" % self.p.approximant pylab.savefig(pname) if self.show_plots: pylab.show() else: pylab.close(f)
def generate_waveform(static_arguments, waveform_params): if static_arguments["approximant"] not in td_approximants(): print("Invalid waveform approximant. Please input" "a valid PyCBC time-series approximant.") quit() sample_length = int(static_arguments["sample_length"] * static_arguments["target_sampling_rate"]) # Collect all the required parameters for the simulation from the given # static and variable parameters simulation_parameters = dict(approximant=static_arguments['approximant'], coa_phase=waveform_params['coa_phase'], delta_f=static_arguments['delta_f'], delta_t=static_arguments['delta_t'], distance=static_arguments['distance'], f_lower=static_arguments['f_lower'], inclination=waveform_params['inclination'], mass1=waveform_params['mass1'], mass2=waveform_params['mass2'], spin1z=waveform_params['spin1z'], spin2z=waveform_params['spin2z'], ra=waveform_params['ra'], dec=waveform_params['dec']) # Perform the actual simulation with the given parameters h_plus, h_cross = get_td_waveform(**simulation_parameters) start_time = np.copy(float(h_plus.start_time)) return h_plus, simulation_parameters, h_plus.sample_times, start_time
def get_waveform(approximant, phase_order, amplitude_order, template_params, start_frequency, sample_rate, length, filter_rate): if approximant in td_approximants(): hplus, hcross = get_td_waveform(template_params, approximant=approximant, phase_order=phase_order, delta_t=1.0 / sample_rate, f_lower=start_frequency, amplitude_order=amplitude_order) hvec = generate_detector_strain(template_params, hplus, hcross) if filter_rate != sample_rate: delta_t = 1.0 / filter_rate hvec = resample_to_delta_t(hvec, delta_t) elif approximant in fd_approximants(): delta_f = filter_rate / length if hasattr(template_params, "spin1z") and hasattr( template_params, "spin2z"): if template_params.spin1z <= -0.9 or template_params.spin1z >= 0.9: template_params.spin1z *= 0.99999999 if template_params.spin2z <= -0.9 or template_params.spin2z >= 0.9: template_params.spin2z *= 0.99999999 if True: print("\n spin1z = %f, spin2z = %f, chi = %f" % (template_params.spin1z, template_params.spin2z, lalsimulation.SimIMRPhenomBComputeChi( template_params.mass1 * lal.LAL_MSUN_SI, template_params.mass2 * lal.LAL_MSUN_SI, template_params.spin1z, template_params.spin2z)), file=sys.stderr) print("spin1x = %f, spin1y = %f" % (template_params.spin1x, template_params.spin1y), file=sys.stderr) print("spin2x = %f, spin2y = %f" % (template_params.spin2x, template_params.spin2y), file=sys.stderr) print("m1 = %f, m2 = %f" % (template_params.mass1, template_params.mass2), file=sys.stderr) hvec = get_fd_waveform(template_params, approximant=approximant, phase_order=phase_order, delta_f=delta_f, f_lower=start_frequency, amplitude_order=amplitude_order)[0] if True: print("filter_N = %d in get waveform" % filter_N, "\n type(hvec) in get_waveform:", type(hvec), file=sys.stderr) print(hvec, file=sys.stderr) print(hvec[0], file=sys.stderr) print(hvec[1], file=sys.stderr) print(isinstance(hvec, FrequencySeries), file=sys.stderr) htilde = make_padded_frequency_series(hvec, filter_N) return htilde
def get_waveform(p, **kwds): """ Given the input parameters get me the waveform, whether it is TD or FD """ params = copy.copy(p.__dict__) params.update(kwds) if params['approximant'] in td_approximants(): return get_td_waveform(**params) else: return get_fd_waveform(**params)
def test_generation(self): with self.context: for waveform in td_approximants(): if waveform in failing_wfs: continue print(waveform) hc,hp = get_td_waveform(approximant=waveform,mass1=20,mass2=20,delta_t=1.0/4096,f_lower=40) self.assertTrue(len(hc)> 0) for waveform in fd_approximants(): if waveform in failing_wfs: continue print(waveform) htilde, g = get_fd_waveform(approximant=waveform,mass1=20,mass2=20,delta_f=1.0/256,f_lower=40) self.assertTrue(len(htilde)> 0)
def get_waveform(wf_params, start_frequency, sample_rate, length, filter_rate, sky_max_template=False): delta_f = filter_rate / float(length) if wf_params.approximant in fd_approximants(): hp, hc = get_fd_waveform(wf_params, delta_f=delta_f, f_lower=start_frequency) elif wf_params.approximant in td_approximants(): hp, hc = get_td_waveform(wf_params, delta_t=1./sample_rate, f_lower=start_frequency) if not sky_max_template: hvec = generate_detector_strain(wf_params, hp, hc) return make_padded_frequency_series(hvec, length, delta_f=delta_f) else: return make_padded_frequency_series(hp, length, delta_f=delta_f), \ make_padded_frequency_series(hc, length, delta_f=delta_f)
def get_waveform(approximant, order, template_params, start_frequency, sample_rate, length): if approximant in fd_approximants(): delta_f = float(sample_rate) / length hvec = get_fd_waveform(template_params, approximant=approximant, phase_order=order, delta_f=delta_f, f_lower=start_frequency, amplitude_order=order) if approximant in td_approximants(): hplus,hcross = get_td_waveform(template_params, approximant=approximant, phase_order=order, delta_t=1.0 / sample_rate, f_lower=start_frequency, amplitude_order=order) hvec = hplus htilde = make_padded_frequency_series(hvec,filter_N) return htilde
def get_waveform(approximant, phase_order, amplitude_order, template_params, start_frequency, sample_rate, length): if approximant in td_approximants(): hplus,hcross = get_td_waveform(template_params, approximant=approximant, phase_order=phase_order, delta_t=1.0 / sample_rate, f_lower=start_frequency, amplitude_order=amplitude_order) hvec = generate_detector_strain(template_params, hplus, hcross) elif approximant in fd_approximants(): delta_f = sample_rate / length hvec = get_fd_waveform(template_params, approximant=approximant, phase_order=phase_order, delta_f=delta_f, f_lower=start_frequency, amplitude_order=amplitude_order) htilde = make_padded_frequency_series(hvec,filter_N) return htilde
def test_generation(self): with self.context: for waveform in td_approximants(): if waveform in failing_wfs: continue print(waveform) hc, hp = get_td_waveform(approximant=waveform, mass1=20, mass2=20, delta_t=1.0 / 4096, f_lower=40) self.assertTrue(len(hc) > 0) for waveform in fd_approximants(): if waveform in failing_wfs: continue print(waveform) htilde, g = get_fd_waveform(approximant=waveform, mass1=20, mass2=20, delta_f=1.0 / 256, f_lower=40) self.assertTrue(len(htilde) > 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
action='store', type='int', dest='devicenum', default=0, help=optparse.SUPPRESS_HELP) parser.add_option('--show-plots', action='store_true', help='show the plots generated in this test suite') parser.add_option('--save-plots', action='store_true', help='save the plots generated in this test suite') parser.add_option('--approximant', type='choice', choices=td_approximants() + fd_approximants(), help="Choices are %s" % str(td_approximants() + fd_approximants())) parser.add_option('--mass1', type=float, default=10, help="[default: %default]") parser.add_option('--mass2', type=float, default=9, help="[default: %default]") parser.add_option('--spin1x', type=float, default=0, help="[default: %default]") parser.add_option('--spin1y', type=float, default=0,
def generate_intrinsic_waveform( sample: Union[np.record, Dict[str, float]], static_args: Dict[str, Union[str, float]], spins: bool=True, spins_aligned: bool=False, # inclination: bool=True, downcast: bool=True, as_pycbc: bool=False, ) -> Union[Tuple[TimeSeries], Tuple[FrequencySeries]]: """Function generates a waveform in either time or frequency domain using PyCBC methods. Arguments: intrinsic: Union[np.record, Dict[str, float]] A one dimensional vector (or dictionary of scalars) of intrinsic parameters that parameterise a given waveform. We require sample to be one row in a because we want to process one waveform at a time, but we want to be able to use the PyCBC prior distribution package which outputs numpy.records. static_args: Dict[str, Union[str, float]] A dictionary of type-casted (from str to floats or str) arguments loaded from an .ini file. We expect keys in this dictionary to specify the approximant, domain, frequency bands, etc. inclination: bool spins: bool spins_aligned: bool downcast: bool If True, downcast from double precision to full precision. E.g. np.complex124 > np.complex64 for frequency, np.float64 > np.float32 for time. Returns: (hp, hc) A tuple of the plus and cross polarizations as pycbc Array types depending on the specified waveform domain (i.e. time or frequency). """ # type checking inputs if isinstance(sample, np.record): assert sample.shape == (), "input array be a 1 dimensional record array. (PyCBC compatibility)" for param in ('mass_1', 'mass_2', 'phase'): if isinstance(sample, np.record): assert param in sample.dtype.names, f"{param} not provided in sample." if isinstance(sample, dict): assert param in sample.keys(), f"{param} not provided in sample." for arg in ('approximant', 'domain','f_lower', 'f_final', 'f_ref'): assert arg in static_args, f"{arg} not provided in static_args." if arg == 'domain': assert static_args['domain'] in ('time', 'frequency'), ( f"{static_args['domain']} is not a valid domain." ) # reference distance - we are generating intrinsic parameters and we scale distance later distance = static_args.get('distance', 1000) # function default is 1, we use 1000 as ref dist # determine parameters conditional on spin and inclination of CBC if spins: if spins_aligned: iota = sample['theta_jn'] # we don't want to overwrite theta_jn if spins not aligned spin_1x, spin_1y, spin_1z = 0., 0., sample['chi_1'] spin_2x, spin_2y, spin_2z = 0., 0., sample['chi_2'] else: # convert from event frame to radiation frame iota, spin_1x, spin_1y, spin_1z, spin_2x, spin_2y, spin_2z = source_frame_to_radiation( sample['mass_1'], sample['mass_2'], sample['phase'], sample['theta_jn'], sample['phi_jl'], sample['tilt_1'], sample['tilt_2'], sample['phi_12'], sample['a_1'], sample['a_2'], static_args['f_ref'], ) else: iota = sample['theta_jn'] spin_1x, spin_1y, spin_1z = 0., 0., 0. spin_2x, spin_2y, spin_2z = 0., 0., 0. if static_args['domain'] in ('time',): # generate time domain waveform assert 'delta_t' in static_args, "delta_t not provided in static_args." assert static_args['approximant'] in td_approximants(), ( f"{static_args['approximant']} is not a valid time domain waveform" ) # TO DO: Handle variable length td_waveform generation. # ValueError: Time series does not contain a time as early as -8. raise NotImplementedError('time domain waveforms not yet implemented.') # Make sure f_min is low enough # if static_args['waveform_length'] > get_waveform_filter_length_in_time( # mass1=sample['mass_1'], mass2=sample['mass_2'], # spin1x=spin_1x, spin2x=spin_2x, # spin1y=spin_1y, spin2y=spin_2y, # spin1z=spin_1z, spin2z=spin_2z, # inclination=iota, # f_lower=static_args['f_lower'], # f_ref=static_args['f_ref'], # approximant=static_args['approximant'], # distance=distance, # ): # print('Warning: f_min not low enough for given waveform duration') # get plus polarisation (hp) and cross polarisation (hc) as time domain waveforms hp, hc = get_td_waveform( mass1=sample['mass_1'], mass2=sample['mass_2'], spin1x=spin_1x, spin2x=spin_2x, spin1y=spin_1y, spin2y=spin_2y, spin1z=spin_1z, spin2z=spin_2z, coa_phase=sample['phase'], inclination=iota, # "Check this!" - Stephen Green delta_t=static_args['delta_t'], f_lower=static_args['f_lower'], f_ref=static_args['f_ref'], approximant=static_args['approximant'], distance=distance, ) # Apply the fade-on filter to them - should be timeseries only? # if static_arguments['domain'] == 'time': # h_plus = fade_on(h_plus, alpha=static_arguments['tukey_alpha']) # h_cross = fade_on(h_cross, alpha=static_arguments['tukey_alpha']) # waveform coalesces at t=0, but t=0 is at end of array # add to start_time s.t. (t=l-ength, t=0) --> (t=0, t=length) hp = hp.time_slice(-int(static_args['waveform_length']), 0.0) hc = hc.time_slice(-int(static_args['waveform_length']), 0.0) hp.start_time += static_args['waveform_length'] hc.start_time += static_args['waveform_length'] # Resize the simulated waveform to the specified length ?? # need to be careful here # hp.resize(static_args['original_sampling_rate']) # hc.resize(static_args['original_sampling_rate']) if downcast: hp = hp.astype(np.float32) hc = hc.astype(np.float32) elif static_args['domain'] in ('frequency',): # generate frequency domain waveform assert 'delta_t' in static_args, "delta_t not provided in static_args." assert static_args['approximant'] in fd_approximants(), ( f"{static_args['approximant']} is not a valid frequency domain waveform" ) hp, hc = get_fd_waveform( mass1=sample['mass_1'], mass2=sample['mass_2'], spin1x=spin_1x, spin2x=spin_2x, spin1y=spin_1y, spin2y=spin_2y, spin1z=spin_1z, spin2z=spin_2z, coa_phase=sample['phase'], inclination=iota, # "Check this!" - Stephen Green delta_f=static_args['delta_f'], f_lower=static_args['f_lower'], f_final=static_args['f_final'], f_ref=static_args['f_ref'], approximant=static_args['approximant'], distance=distance, ) # time shift - should we do this when we create or project the waveform? hp = hp.cyclic_time_shift(static_args['seconds_before_event']) hc = hc.cyclic_time_shift(static_args['seconds_before_event']) hp.start_time += static_args['seconds_before_event'] hc.start_time += static_args['seconds_before_event'] if downcast: hp = hp.astype(np.complex64) hc = hc.astype(np.complex64) if as_pycbc: return hp, hc return hp.data, hc.data
# zero-out everything after ffinal # crossing_point = \ # NR_freqs.sample_times[ # np.isclose(NR_freqs,ffinal,1/hplus_NR.sample_times[-1])[0] # ] # hplus_NR.data[int(hplus_NR.sample_times>crossing_point)] = 0.0 # hcross_NR.data[int(hcross_NR.sample_times>crossing_point)] = 0.0 # hplus_NR = wfutils.taper_timeseries(hplus_NR, "TAPER_STARTEND") hcross_NR = wfutils.taper_timeseries(hcross_NR, "TAPER_STARTEND") # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # APPROXIMANT # if approx == 'SEOBNRv2': if approx in td_approximants(): hplus_approx, hcross_approx = get_td_waveform( approximant=approx, distance=distance, mass1=mass1, mass2=mass2, spin1x=0.0, spin2x=0.0, spin1y=0.0, spin2y=0.0, spin1z=simulations.simulations[0]["spin1z"], spin2z=simulations.simulations[0]["spin2z"], inclination=inc, f_lower=f_low_approx * min(masses) / mass, delta_t=delta_t,
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
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
parser.add_option("--match-file", dest="out_file", help="file to output match results", metavar="FILE") #PSD Settings parser.add_option("--asd-file", dest="asd_file", help="two-column ASCII file containing ASD data", metavar="FILE") parser.add_option("--psd", dest="psd", help="Analytic PSD model from LALSimulation", choices=pycbc.psd.get_lalsim_psd_list()) aprs = list(set(td_approximants() + fd_approximants())) #Template Settings parser.add_option( "--template-file", dest="bank_file", help= "SimInspiral or SnglInspiral XML file containing the template parameters.", metavar="FILE") parser.add_option("--template-approximant", help="Template Approximant Name: " + str(aprs), choices=aprs) parser.add_option("--template-phase-order", help="PN order to use for the phase", default=-1, type=int) parser.add_option("--template-amplitude-order",
from pycbc.waveform import td_approximants, fd_approximants # List of td approximants that are available print td_approximants() # List of fd approximants that are currently available print fd_approximants() # Note that these functions only print what is available for your current # processing context. If a waveform is implemented in CUDA or OpenCL, it will # only be listed when running under a CUDA or OpenCL Scheme.
return htilde ############################################################################### #File output Settings parser = OptionParser() parser.add_option("--match-file", dest="out_file", help="file to output match results", metavar="FILE") #PSD Settings parser.add_option("--asd-file", dest="asd_file", help="two-column ASCII file containing ASD data", metavar="FILE") parser.add_option("--psd", dest="psd", help="Analytic PSD model from LALSimulation", choices=pycbc.psd.get_lalsim_psd_list()) aprs = list(set(td_approximants() + fd_approximants())) #Template Settings parser.add_option("--template-file", dest="bank_file", help="SimInspiral or SnglInspiral XML file containing the template parameters.", metavar="FILE") parser.add_option("--template-approximant",help="Template Approximant Name: " + str(aprs), choices = aprs) parser.add_option("--template-phase-order",help="PN order to use for the phase",default=-1,type=int) parser.add_option("--template-amplitude-order",help="PN order to use for the amplitude",default=-1,type=int) parser.add_option("--template-start-frequency",help="Starting frequency for injections",type=float) parser.add_option("--template-sample-rate",help="Starting frequency for injections",type=float) #Signal Settings parser.add_option("--signal-file", dest="sim_file", help="SimInspiral or SnglInspiral XML file containing the signal parameters.", metavar="FILE") parser.add_option("--signal-approximant",help="Signal Approximant Name: " + str(aprs), choices = aprs) parser.add_option("--signal-phase-order",help="PN order to use for the phase",default=-1,type=int) parser.add_option("--signal-amplitude-order",help="PN order to use for the amplitude",default=-1,type=int) parser.add_option("--signal-start-frequency",help="Starting frequency for templates",type=float) parser.add_option("--signal-sample-rate",help="Starting frequency for templates",type=float)
x_axis_label='time(sec)', y_axis_label='rad', plot_width=500, plot_height=400) pn44.line(x='timeTD', y='phaseTD', source=sourcep42, color='red', line_width=3) pn44.toolbar.logo = None q_slider = Slider(start=1, end=10, value=1, step=.5, title="Mass ratio (q)") e_slider = Slider(start=0., end=0.9, value=0, step=.05, title="Eccentricity (e)") s1z_slider = Slider(start=-1, end=1, value=0, step=.05, title="Spin1z") s2z_slider = Slider(start=-1, end=1, value=0, step=.05, title="Spin2z") model_select = Select(title="TD Models", options=td_approximants()) def update_slider2(attrname, old, new): # Get the current slider values q = q_slider.value e = e_slider.value s1z = s1z_slider.value s2z = s2z_slider.value approximant = model_select.value timeTD, hp_realTD, hc_realTD, hp_imagTD, hc_imagTD, ampTD, phaseTD = generate_TD_waveform( mass_rat=q, eccentricity=e, s1z=s1z, s2z=s2z, approximant=approximant) sourcep42.data = { 'hp_realTD': hp_realTD, 'hc_realTD': hc_realTD, 'hp_imagTD': hp_imagTD,
import lalsimulation import matplotlib.pyplot as plt from scipy import interpolate from numpy import pi from scipy import constants from pycbc.conversions import * from astropy import cosmology from pycbc import waveform """Waveform approximants, that model waveforms, are imported.""" from pycbc.waveform import td_approximants, fd_approximants # with pycbc.waveform can create model waveforms # List of td approximants thsqat are currently available print(td_approximants()) # prints all the possible model waveforms """The data used were fetched online. All the events downloaded from these websites. Later on, we will look at only one of the events.""" !wget -nc https://dcc.ligo.org/public/0146/P1700349/001/H-H1_LOSC_CLN_4_V1-1187007040-2048.gwf !wget -nc https://dcc.ligo.org/public/0146/P1700349/001/L-L1_LOSC_CLN_4_V1-1187007040-2048.gwf """Pick the event with the code *GW170817*. We pick the time frame from 224 seconds before merging and end 32 seconds after merging.""" # Commented out IPython magic to ensure Python compatibility. # %matplotlib inline import pylab from pycbc.filter import highpass from pycbc.catalog import Merger from pycbc.frame import read_frame
parser = optparse.OptionParser() parser.add_option('--scheme','-s', action='callback', type = 'choice', choices = ('cpu','cuda'), default = 'cpu', dest = 'scheme', callback = _check_scheme_cpu, help = optparse.SUPPRESS_HELP) parser.add_option('--device-num','-d', action='store', type = 'int', dest = 'devicenum', default=0, help = optparse.SUPPRESS_HELP) parser.add_option('--show-plots', action='store_true', help = 'show the plots generated in this test suite') parser.add_option('--save-plots', action='store_true', help = 'save the plots generated in this test suite') parser.add_option('--approximant', type = 'choice', choices = td_approximants() + fd_approximants(), help = "Choices are %s" % str(td_approximants() + fd_approximants())) parser.add_option('--mass1', type = float, default=10, help = "[default: %default]") parser.add_option('--mass2', type = float, default=10, help = "[default: %default]") parser.add_option('--spin1x', type = float, default=0, help = "[default: %default]") parser.add_option('--spin1y', type = float, default=0, help = "[default: %default]") parser.add_option('--spin1z', type = float, default=0, help = "[default: %default]") parser.add_option('--spin2x', type = float, default=0, help = "[default: %default]") parser.add_option('--spin2y', type = float, default=0, help = "[default: %default]") parser.add_option('--spin2z', type = float, default=0, help = "[default: %default]") parser.add_option('--lambda1', type = float, default=0, help = "[default: %default]") parser.add_option('--lambda2', type = float, default=0, help = "[default: %default]") parser.add_option('--coa-phase', type = float, default=0, help = "[default: %default]") parser.add_option('--inclination', type = float, default=0, help = "[default: %default]")
parser = optparse.OptionParser() parser.add_option('--scheme','-s', action='callback', type = 'choice', choices = ('cpu','cuda'), default = 'cpu', dest = 'scheme', callback = _check_scheme_cpu, help = optparse.SUPPRESS_HELP) parser.add_option('--device-num','-d', action='store', type = 'int', dest = 'devicenum', default=0, help = optparse.SUPPRESS_HELP) parser.add_option('--show-plots', action='store_true', help = 'show the plots generated in this test suite') parser.add_option('--save-plots', action='store_true', help = 'save the plots generated in this test suite') parser.add_option('--approximant', type = 'choice', choices = td_approximants() + fd_approximants(), help = "Choices are %s" % str(td_approximants() + fd_approximants())) parser.add_option('--mass1', type = float, default=10, help = "[default: %default]") parser.add_option('--mass2', type = float, default=9, help = "[default: %default]") parser.add_option('--spin1x', type = float, default=0, help = "[default: %default]") parser.add_option('--spin1y', type = float, default=0, help = "[default: %default]") parser.add_option('--spin1z', type = float, default=0, help = "[default: %default]") parser.add_option('--spin2x', type = float, default=0, help = "[default: %default]") parser.add_option('--spin2y', type = float, default=0, help = "[default: %default]") parser.add_option('--spin2z', type = float, default=0, help = "[default: %default]") parser.add_option('--lambda1', type = float, default=0, help = "[default: %default]") parser.add_option('--lambda2', type = float, default=0, help = "[default: %default]") parser.add_option('--coa-phase', type = float, default=0, help = "[default: %default]") parser.add_option('--inclination', type = float, default=0, help = "[default: %default]")
from pycbc.waveform import td_approximants, fd_approximants # List of td approximants that are available print(td_approximants()) # List of fd approximants that are currently available print(fd_approximants()) # Note that these functions only print what is available for your current # processing context. If a waveform is implemented in CUDA or OpenCL, it will # only be listed when running under a CUDA or OpenCL Scheme.
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]
def one_det_main(input_file_name="default.hdf", template_file_name="default_templates.hdf", output_file_name="default_snrs.hdf", snr_range="default"): # ----------------------------------------------------------------------------- # Preliminaries # ----------------------------------------------------------------------------- # Disable output buffering ('flush' option is not available for Python 2) #sys.stderr = os.fdopen(sys.stderr.fileno(), 'w', 0) # Start the stopwatch script_start = time.time() #multiprocessing.log_to_stderr() #logger = multiprocessing.get_logger() #logger.setLevel(logging.DEBUG) print('') print('GENERATE A GW SAMPLE SNR TIME-SERIES') print('') # ----------------------------------------------------------------------------- # Parse the command line arguments # ----------------------------------------------------------------------------- # Set up the parser and add arguments parser = argparse.ArgumentParser(description='Generate a GW data sample.') # Add arguments (and set default values where applicable) parser.add_argument('--config-file', help='Name of the JSON configuration file which ' 'controls the sample generation process.', default='default.json') parser.add_argument('--filter-injection-samples', help='Boolean expression for whether to' 'calculate SNRs of injection signals.' 'Default: True', default=True) parser.add_argument('--filter-templates', help='Boolean expression for whether to calculate' 'SNRs of all signals using a set of templates.' 'Default: True', default=True) parser.add_argument('--trim-output', help='Boolean expression for whether to trim the' 'SNR time series output.' 'Default: True', default=True) # Parse the arguments that were passed when calling this script print('Parsing command line arguments...', end=' ') arguments = vars(parser.parse_args()) print('Done!') # Set up shortcut for the command line arguments filter_injection_samples = bool(arguments['filter_injection_samples']) filter_templates = bool(arguments['filter_templates']) trim_output = bool(arguments['trim_output']) # ------------------------------------------------------------------------- # Read in JSON config file specifying the sample generation process # ------------------------------------------------------------------------- # Build the full path to the config file json_config_name = arguments['config_file'] json_config_path = os.path.join('.', 'config_files', json_config_name) # Read the JSON configuration into a dict print('Reading and validating in JSON configuration file...', end=' ') config = read_json_config(json_config_path) print('Done!') # ------------------------------------------------------------------------- # Read in INI config file specifying the static_args and variable_args # ------------------------------------------------------------------------- # Build the full path to the waveform params file ini_config_name = config['waveform_params_file_name'] ini_config_path = os.path.join('.', 'config_files', ini_config_name) # Read in the variable_arguments and static_arguments print('Reading and validating in INI configuration file...', end=' ') variable_arguments, static_arguments = read_ini_config(ini_config_path) print('Done!\n') # Check output file directory exists output_dir = os.path.join('.', 'output') if snr_range == "default": samples_output_dir = output_dir else: samples_output_dir = os.path.join(output_dir, snr_range) if not os.path.exists(samples_output_dir): print("Output folder cannot be found. Please create a folder", "named 'output' to store data in.") quit() # Get file names from config file if template_file_name == "default_templates.hdf": templates_file_path = os.path.join(output_dir, config['template_output_file_name']) else: templates_file_path = os.path.join(output_dir, template_file_name) if input_file_name == "default.hdf": input_file_path = os.path.join(samples_output_dir, config['output_file_name']) else: input_file_path = os.path.join(samples_output_dir, input_file_name) if output_file_name == "default_snrs.hdf": output_file_path = os.path.join(output_dir, config['snr_output_file_name']) else: output_file_path = os.path.join(samples_output_dir, output_file_name) # ------------------------------------------------------------------------- # Read in the sample file # ------------------------------------------------------------------------- print('Reading in samples HDF file...', end=' ') df = h5py.File(input_file_path, 'r') print('Done!') # ------------------------------------------------------------------------- # Create dataframe column to store SNR time-series # ------------------------------------------------------------------------- # Get approximant for generating matched filter templates from config files if static_arguments["approximant"] not in td_approximants(): print("Invalid waveform approximant. Please put a valid time-series" "approximant in the waveform params file..") quit() apx = static_arguments["approximant"] sample_length = static_arguments[ "seconds_before_event"] + static_arguments["seconds_after_event"] delta_f = 1.0 / sample_length # Get f-lower and delta-t from config files f_low = static_arguments["f_lower"] delta_t = 1.0 / static_arguments["target_sampling_rate"] # Initialise list of all parameters required for generating template waveforms param_dict = dict(injections=dict(mass1=[], mass2=[], spin1z=[], spin2z=[], ra=[], dec=[], coa_phase=[], inclination=[], polarization=[], injection_snr=[], f_lower=f_low, approximant=apx, delta_t=delta_t)) # Store number of injection samples, should be identical for all detectors n_injection_samples = config['n_injection_samples'] # Store number of noise samples, should be identical for all detectors n_noise_samples = config['n_noise_samples'] # Store number of templates n_templates = config['n_template_samples'] # Get trim cutoff trim_cutoff_low = config['snr_output_cutoff_low'] * static_arguments[ "target_sampling_rate"] trim_cutoff_high = config['snr_output_cutoff_high'] * static_arguments[ "target_sampling_rate"] trim_cutoff_variation = config[ 'snr_output_cutoff_variation'] * static_arguments[ "target_sampling_rate"] / 2 # Initialize arrays for random offset values inj_low, inj_high, noise_low, noise_high, temp_inj_low, temp_inj_high = ( [] for i in range(6)) # Generate random time shits and apply to start and end times for each type of sample for i in range(n_injection_samples): rand = random.randint(-trim_cutoff_variation, trim_cutoff_variation) rand_low = trim_cutoff_low + rand rand_high = trim_cutoff_high + rand inj_low.append(rand_low) inj_high.append(rand_high) for i in range(n_noise_samples * n_templates): rand = random.randint(-trim_cutoff_variation, trim_cutoff_variation) rand_low = trim_cutoff_low + rand rand_high = trim_cutoff_high + rand noise_low.append(rand_low) noise_high.append(rand_high) for i in range(n_injection_samples * n_templates): rand = random.randint(-trim_cutoff_variation, trim_cutoff_variation) rand_low = trim_cutoff_low + rand rand_high = trim_cutoff_high + rand temp_inj_low.append(rand_low) temp_inj_high.append(rand_high) # ------------------------------------------------------------------------- # Compute SNR time-series # ------------------------------------------------------------------------- # Generate optimal SNR time series if filter_injection_samples: print('Generating OMF SNR time-series for injection samples...') if n_injection_samples > 0: injections_build_files = InjectionsBuildFiles( output_file_path=output_file_path, param_dict=param_dict, df=df, n_samples=n_injection_samples, trim_output=trim_output, inj_low=inj_low, inj_high=inj_high) injections_build_files.run() print('Done!') else: print('Done! (n-samples = 0)\n') else: print('No SNR time-series generated for injections.' 'Please set filter-injection-samples to True.') # Generate SNR time series with template bank, using injection and noise samples if filter_templates: print('Reading in the templates HDF file...', end=' ') templates_df = h5py.File(templates_file_path, 'r') print('Done!') print( "Generating SNR time-series for injection and noise samples using a template set..." ) if n_templates == 0: print('Done! (n-templates = 0)' 'Please generate templates before running.\n') elif (n_noise_samples > 0) or (n_injection_samples > 0): filters_build_files = FiltersBuildFiles( output_file_path=output_file_path, df=df, templates_df=templates_df, n_noise_samples=n_noise_samples, n_injection_samples=n_injection_samples, n_templates=n_templates, f_low=f_low, delta_t=delta_t, filter_injection_samples=filter_injection_samples, delta_f=delta_f, trim_output=trim_output, inj_low=temp_inj_low, inj_high=temp_inj_high, noise_low=noise_low, noise_high=noise_high) filters_build_files.run() print('Done!') else: print('Done! (n-noise-samples = 0)\n') else: print('No SNR time-series generated for injections.' 'Please set filter-templates to True.') # Get file size in MB and print the result sample_file_size = os.path.getsize(output_file_path) / 1024**2 print('Size of resulting HDF file: {:.2f}MB'.format(sample_file_size)) print('') # ------------------------------------------------------------------------- # Postliminaries # ------------------------------------------------------------------------- # Print the total run time print('Total runtime: {:.1f} seconds!'.format(time.time() - script_start)) print('')