Ejemplo n.º 1
0
    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")
Ejemplo n.º 2
0
    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')
Ejemplo n.º 3
0
    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')
Ejemplo n.º 4
0
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
Ejemplo n.º 5
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
Ejemplo n.º 6
0
def calculate_fitting_factor(m1, m2,
                             s1x=0, s1y=0, s1z=0,
                             s2x=0, s2y=0, s2z=0,
                             tc=0, phic=0,
                             ra=0, dec=0, polarization=0,
                             signal_approx='IMRPhenomD',
                             signal_file=None,
                             tmplt_approx='IMRPhenomC',
                             vary_masses_only=True,
                             vary_masses_and_aligned_spin_only=False,
                             chirp_mass_window=0.1,
                             effective_spin_window=0.5,
                             num_retries=4,
                             f_lower=15.0,
                             sample_rate=4096,
                             signal_duration=256,
                             psd_string='aLIGOZeroDetHighPower',
                             pso_swarm_size=500,
                             pso_omega=0.5,
                             pso_phip=0.5,
                             pso_phig=0.25,
                             pso_minfunc=1e-8,
                             verbose=True,
                             debug=False):
    """
Calculates the fitting factor for a signal of given physical
parameters, as modelled by a given signal approximant, against
templates of another approximant.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        retval = np.log10(1. - m)

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

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

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

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

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

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

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

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

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

    if verbose:
        print("optimization took %d objective func evals" %
              objective_function_fitting_factor.counter)
        sys.stdout.flush()
    #
    # 7) RETURN OPTIMIZED PARAMETERS
    return [params, olap, ff]
Ejemplo n.º 7
0
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