def psd(self, psd): if callable(psd): self.__psd = psd(self.nsamples, self.deltaf, self.flow) elif isinstance(psd, FrequencySeries): # make sure values below flow are zero kmin = int(self.flow / self.deltaf) psd.data[:kmin] = 0 self.__psd = psd elif isinstance(psd, str): # try reading PSD from file try: self.__psd = from_txt( psd, self.nsamples, self.deltaf, self.flow, is_asd_file=self.is_asd_file, ) except Exception as e1: # try getting PSD from string name try: self.__psd = from_string(psd, self.nsamples, self.deltaf, self.flow) except Exception as e2: raise IOError("Could not create PSD: {}\n{}".format(e1, e2)) elif isinstance(psd, float): # convert single float into PSD FrequencySeries val = psd ** 2 if self.is_asd_file else psd psds = np.full(self.nsamples, val) kmin = int(self.flow / self.deltaf) psds[:kmin] = 0 self.__psd = FrequencySeries(psds, delta_f=self.deltaf) else: raise TypeError("Could not create PSD from supplied input")
def setUp(self, *args): # Where are my data files? if os.path.isfile('test/data/ZERO_DET_high_P.txt'): self.dataDir = 'test/data/' elif os.path.isfile('data/ZERO_DET_high_P.txt'): self.dataDir = 'data/' else: self.assertTrue(False, msg="Cannot find data files!") self.context = _context self.scheme = _scheme self.tolerance = 1e-6 self.filter_t_length = 16 self.low_freq_filter = 30. self.sample_rate = 16384 self.filter_N = self.filter_t_length * self.sample_rate self.filter_n = self.filter_N / 2 + 1 self.filter_delta_f = 1.0 / self.filter_t_length self.psd = psd.from_string('aLIGOZeroDetHighPowerGWINC', self.filter_n, self.filter_delta_f, self.low_freq_filter) self.psd *= DYN_RANGE_FAC*DYN_RANGE_FAC wps1 = DummyClass() wps1.mass1 = 123.7627 wps1.mass2 = 72.55471 wps1.inclination = 1.125029 wps1.coa_phase = 2.906049 wps1.approximant='EOBNRv2HM' self.wps1 = wps1 wps2 = DummyClass() wps2.mass1 = 131.460647583 wps2.mass2 = 69.0030059814 wps2.inclination = 0.8432287 wps2.coa_phase = 0.2 wps2.approximant = 'SEOBNRv4_ROM' self.wps2 = wps2 wps3 = copy.deepcopy(wps2) wps3.approximant = 'EOBNRv2HM_ROM' self.wps3 = wps3 wps4 = copy.deepcopy(wps2) wps4.spin1x = 0.8 wps4.spin2y = -0.9 wps4.approximant = 'IMRPhenomPv2' self.wps4 = wps4 self.wps_list = [wps1, wps2, wps3, wps4] self.sm_power_chisq = vetoes.SingleDetSkyMaxPowerChisq(num_bins='1') self.sm_power_chisq2 = vetoes.SingleDetSkyMaxPowerChisq(num_bins='10') self.power_chisq = vetoes.SingleDetPowerChisq(num_bins='1') self.power_chisq2 = vetoes.SingleDetPowerChisq(num_bins='10')
def setUp(self, *args): # Where are my data files? if os.path.isfile('test/data/ZERO_DET_high_P.txt'): self.dataDir = 'test/data/' elif os.path.isfile('data/ZERO_DET_high_P.txt'): self.dataDir = 'data/' else: self.assertTrue(False, msg="Cannot find data files!") self.context = _context self.scheme = _scheme self.tolerance = 1e-6 self.filter_t_length = 16 self.low_freq_filter = 30. self.sample_rate = 16384 self.filter_N = int(self.filter_t_length * self.sample_rate) self.filter_n = int(self.filter_N / 2 + 1) self.filter_delta_f = 1.0 / self.filter_t_length self.psd = psd.from_string('aLIGOZeroDetHighPowerGWINC', self.filter_n, self.filter_delta_f, self.low_freq_filter) self.psd *= DYN_RANGE_FAC*DYN_RANGE_FAC wps1 = DummyClass() wps1.mass1 = 123.7627 wps1.mass2 = 72.55471 wps1.inclination = 1.125029 wps1.coa_phase = 2.906049 wps1.approximant='EOBNRv2HM' self.wps1 = wps1 wps2 = DummyClass() wps2.mass1 = 131.460647583 wps2.mass2 = 69.0030059814 wps2.inclination = 0.8432287 wps2.coa_phase = 0.2 wps2.approximant = 'SEOBNRv4_ROM' self.wps2 = wps2 wps3 = copy.deepcopy(wps2) wps3.approximant = 'EOBNRv2HM_ROM' self.wps3 = wps3 wps4 = copy.deepcopy(wps2) wps4.spin1x = 0.8 wps4.spin2y = -0.9 wps4.approximant = 'IMRPhenomPv2' self.wps4 = wps4 self.wps_list = [wps1, wps2, wps3, wps4] self.sm_power_chisq = vetoes.SingleDetSkyMaxPowerChisq(num_bins='1') self.sm_power_chisq2 = vetoes.SingleDetSkyMaxPowerChisq(num_bins='10') self.power_chisq = vetoes.SingleDetPowerChisq(num_bins='1') self.power_chisq2 = vetoes.SingleDetPowerChisq(num_bins='10')
def from_cli(opt, dyn_range_fac=1, precision='single'): """Parses the CLI options related to strain data reading and conditioning. Parameters ---------- opt : object Result of parsing the CLI with OptionParser, or any object with the required attributes (gps-start-time, gps-end-time, strain-high-pass, pad-data, sample-rate, (frame-cache or frame-files), channel-name, fake-strain, fake-strain-seed, gating_file). dyn_range_fac: {float, 1}, optional A large constant to reduce the dynamic range of the strain. Returns ------- strain : TimeSeries The time series containing the conditioned strain data. """ if opt.frame_cache or opt.frame_files: if opt.frame_cache: frame_source = opt.frame_cache if opt.frame_files: frame_source = opt.frame_files logging.info("Reading Frames") strain = read_frame(frame_source, opt.channel_name, start_time=opt.gps_start_time-opt.pad_data, end_time=opt.gps_end_time+opt.pad_data) if opt.zpk_z and opt.zpk_p and opt.zpk_k: logging.info("Highpass Filtering") strain = highpass(strain, frequency=opt.strain_high_pass) logging.info("Applying zpk filter") z = numpy.array(opt.zpk_z) p = numpy.array(opt.zpk_p) k = float(opt.zpk_k) strain = filter_zpk(strain.astype(numpy.float64), z, p, k) if opt.normalize_strain: logging.info("Dividing strain by constant") l = opt.normalize_strain strain = strain / l if opt.injection_file: logging.info("Applying injections") injections = InjectionSet(opt.injection_file) injections.apply(strain, opt.channel_name[0:2]) if opt.sgburst_injection_file: logging.info("Applying sine-Gaussian burst injections") injections = SGBurstInjectionSet(opt.sgburst_injection_file) injections.apply(strain, opt.channel_name[0:2]) logging.info("Highpass Filtering") strain = highpass(strain, frequency=opt.strain_high_pass) if precision == 'single': logging.info("Converting to float32") strain = (strain * dyn_range_fac).astype(float32) if opt.gating_file is not None: logging.info("Gating glitches") gate_params = numpy.loadtxt(opt.gating_file) if len(gate_params.shape) == 1: gate_params = [gate_params] strain = gate_data( strain, gate_params, data_start_time=(opt.gps_start_time - opt.pad_data)) logging.info("Resampling data") strain = resample_to_delta_t(strain, 1.0/opt.sample_rate, method='ldas') logging.info("Highpass Filtering") strain = highpass(strain, frequency=opt.strain_high_pass) logging.info("Remove Padding") start = opt.pad_data*opt.sample_rate end = len(strain)-opt.sample_rate*opt.pad_data strain = strain[start:end] if opt.fake_strain: logging.info("Generating Fake Strain") duration = opt.gps_end_time - opt.gps_start_time tlen = duration * opt.sample_rate pdf = 1.0/128 plen = int(opt.sample_rate / pdf) / 2 + 1 logging.info("Making PSD for strain") strain_psd = psd.from_string(opt.fake_strain, plen, pdf, opt.low_frequency_cutoff) logging.info("Making colored noise") strain = pycbc.noise.noise_from_psd(tlen, 1.0/opt.sample_rate, strain_psd, seed=opt.fake_strain_seed) strain._epoch = lal.LIGOTimeGPS(opt.gps_start_time) if opt.injection_file: logging.info("Applying injections") injections = InjectionSet(opt.injection_file) injections.apply(strain, opt.channel_name[0:2]) if opt.sgburst_injection_file: logging.info("Applying sine-Gaussian burst injections") injections = SGBurstInjectionSet(opt.sgburst_injection_file) injections.apply(strain, opt.channel_name[0:2]) if precision == 'single': logging.info("Converting to float32") strain = (dyn_range_fac * strain).astype(float32) if opt.injection_file: strain.injections = injections return strain
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
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 from_cli(opt, dyn_range_fac=1, precision='single'): """Parses the CLI options related to strain data reading and conditioning. Parameters ---------- opt : object Result of parsing the CLI with OptionParser, or any object with the required attributes (gps-start-time, gps-end-time, strain-high-pass, pad-data, sample-rate, (frame-cache or frame-files), channel-name, fake-strain, fake-strain-seed, gating_file). dyn_range_fac: {float, 1}, optional A large constant to reduce the dynamic range of the strain. Returns ------- strain : TimeSeries The time series containing the conditioned strain data. """ if opt.frame_cache or opt.frame_files or opt.frame_type: if opt.frame_cache: frame_source = opt.frame_cache if opt.frame_files: frame_source = opt.frame_files logging.info("Reading Frames") if opt.frame_type: strain = query_and_read_frame(opt.frame_type, opt.channel_name, start_time=opt.gps_start_time-opt.pad_data, end_time=opt.gps_end_time+opt.pad_data) else: strain = read_frame(frame_source, opt.channel_name, start_time=opt.gps_start_time-opt.pad_data, end_time=opt.gps_end_time+opt.pad_data) if opt.zpk_z and opt.zpk_p and opt.zpk_k: logging.info("Highpass Filtering") strain = highpass(strain, frequency=opt.strain_high_pass) logging.info("Applying zpk filter") z = numpy.array(opt.zpk_z) p = numpy.array(opt.zpk_p) k = float(opt.zpk_k) strain = filter_zpk(strain.astype(numpy.float64), z, p, k) if opt.normalize_strain: logging.info("Dividing strain by constant") l = opt.normalize_strain strain = strain / l if opt.injection_file: logging.info("Applying injections") injections = InjectionSet(opt.injection_file) injections.apply(strain, opt.channel_name[0:2]) if opt.sgburst_injection_file: logging.info("Applying sine-Gaussian burst injections") injections = SGBurstInjectionSet(opt.sgburst_injection_file) injections.apply(strain, opt.channel_name[0:2]) logging.info("Highpass Filtering") strain = highpass(strain, frequency=opt.strain_high_pass) if precision == 'single': logging.info("Converting to float32") strain = (strain * dyn_range_fac).astype(float32) if opt.gating_file is not None: logging.info("Gating glitches") gate_params = numpy.loadtxt(opt.gating_file) if len(gate_params.shape) == 1: gate_params = [gate_params] strain = gate_data(strain, gate_params) if opt.autogating_threshold is not None: # the + 0 is for making a copy glitch_times = detect_loud_glitches( strain + 0., threshold=opt.autogating_threshold, cluster_window=opt.autogating_cluster, low_freq_cutoff=opt.strain_high_pass, high_freq_cutoff=opt.sample_rate/2, corrupted_time=opt.pad_data) gate_params = [[gt, opt.autogating_width, opt.autogating_taper] \ for gt in glitch_times] if opt.autogating_output: with file(opt.autogating_output, 'wb') as autogates: for x, y, z in gate_params: autogates.write('%.3f %f %f\n' % (x, y, z)) logging.info('Autogating at %s', ', '.join(['%.3f' % gt for gt in glitch_times])) strain = gate_data(strain, gate_params) logging.info("Resampling data") strain = resample_to_delta_t(strain, 1.0/opt.sample_rate, method='ldas') logging.info("Highpass Filtering") strain = highpass(strain, frequency=opt.strain_high_pass) logging.info("Remove Padding") start = opt.pad_data*opt.sample_rate end = len(strain)-opt.sample_rate*opt.pad_data strain = strain[start:end] if opt.fake_strain: logging.info("Generating Fake Strain") duration = opt.gps_end_time - opt.gps_start_time tlen = duration * opt.sample_rate pdf = 1.0/128 plen = int(opt.sample_rate / pdf) / 2 + 1 logging.info("Making PSD for strain") strain_psd = psd.from_string(opt.fake_strain, plen, pdf, opt.low_frequency_cutoff) logging.info("Making colored noise") strain = pycbc.noise.noise_from_psd(tlen, 1.0/opt.sample_rate, strain_psd, seed=opt.fake_strain_seed) strain._epoch = lal.LIGOTimeGPS(opt.gps_start_time) if opt.injection_file: logging.info("Applying injections") injections = InjectionSet(opt.injection_file) injections.apply(strain, opt.channel_name[0:2]) if opt.sgburst_injection_file: logging.info("Applying sine-Gaussian burst injections") injections = SGBurstInjectionSet(opt.sgburst_injection_file) injections.apply(strain, opt.channel_name[0:2]) if precision == 'single': logging.info("Converting to float32") strain = (dyn_range_fac * strain).astype(float32) if opt.injection_file: strain.injections = injections return strain