コード例 #1
0
ファイル: bank.py プロジェクト: gravity-waves/pycbc
    def __getitem__(self, index):
        if isinstance(index, slice):
            return self.getslice(index)

        approximant = self.approximant(index)
        f_end = self.end_frequency(index)

        # Determine the length of time of the filter, rounded up to
        # nearest power of two
        min_buffer = .5 + self.minimum_buffer
    
        from pycbc.waveform.waveform import props
        buff_size = pycbc.waveform.get_waveform_filter_length_in_time(approximant, f_lower=self.f_lower, 
                                                                      **props(self.table[index]))
        tlen = self.round_up((buff_size + min_buffer) * self.sample_rate)
        flen = tlen / 2 + 1

        delta_f = self.sample_rate / float(tlen)

        if f_end is None or f_end >= (flen * delta_f):
            f_end = (flen-1) * delta_f

        logging.info("Generating %s, %ss, %i" % (approximant, 1.0/delta_f, index))

        # Get the waveform filter
        distance = 1.0 / DYN_RANGE_FAC
        htilde = pycbc.waveform.get_waveform_filter(
            zeros(flen, dtype=numpy.complex64), self.table[index],
            approximant=approximant, f_lower=self.f_lower, f_final=f_end,
            delta_f=delta_f, delta_t=1.0/self.sample_rate, distance=distance,
            **self.extra_args)

        # If available, record the total duration (which may
        # include ringdown) and the duration up to merger since they will be 
        # erased by the type conversion below.
        ttotal = template_duration = -1
        if hasattr(htilde, 'length_in_time'):
                ttotal = htilde.length_in_time
        if hasattr(htilde, 'chirp_length'):
                template_duration = htilde.chirp_length

        self.table[index].template_duration = template_duration        

        htilde = htilde.astype(numpy.complex64)
        htilde.f_lower = self.f_lower
        htilde.end_frequency = f_end
        htilde.end_idx = int(htilde.end_frequency / htilde.delta_f)
        htilde.params = self.table[index]
        htilde.approximant = approximant
        htilde.chirp_length = template_duration
        htilde.length_in_time = ttotal
        
        # Add sigmasq as a method of this instance
        htilde.sigmasq = types.MethodType(sigma_cached, htilde)
        htilde._sigmasq = {}

        htilde.id = self.id_from_hash(hash((htilde.params.mass1, htilde.params.mass2, 
                          htilde.params.spin1z, htilde.params.spin2z)))
        return htilde
コード例 #2
0
    def get_decompressed_waveform(self,
                                  tempout,
                                  index,
                                  f_lower=None,
                                  approximant=None,
                                  df=None):
        """Returns a frequency domain decompressed waveform for the template
        in the bank corresponding to the index taken in as an argument. The
        decompressed waveform is obtained by interpolating in frequency space,
        the amplitude and phase points for the compressed template that are
        read in from the bank."""

        from pycbc.waveform.waveform import props
        from pycbc.waveform import get_waveform_filter_length_in_time

        # Get the template hash corresponding to the template index taken in as argument
        tmplt_hash = self.table.template_hash[index]

        # Read the compressed waveform from the bank file
        compressed_waveform = pycbc.waveform.compress.CompressedWaveform.from_hdf(
            self.filehandler, tmplt_hash, load_now=True)

        # Get the interpolation method to be used to decompress the waveform
        if self.waveform_decompression_method is not None:
            decompression_method = self.waveform_decompression_method
        else:
            decompression_method = compressed_waveform.interpolation
        logging.info("Decompressing waveform using %s", decompression_method)

        if df is not None:
            delta_f = df
        else:
            delta_f = self.delta_f

        # Create memory space for writing the decompressed waveform
        decomp_scratch = FrequencySeries(tempout[0:self.filter_length],
                                         delta_f=delta_f,
                                         copy=False)

        # Get the decompressed waveform
        hdecomp = compressed_waveform.decompress(
            out=decomp_scratch,
            f_lower=f_lower,
            interpolation=decompression_method)
        p = props(self.table[index])
        p.pop('approximant')
        try:
            tmpltdur = self.table[index].template_duration
        except AttributeError:
            tmpltdur = None
        if tmpltdur is None or tmpltdur == 0.0:
            tmpltdur = get_waveform_filter_length_in_time(approximant, **p)
        hdecomp.chirp_length = tmpltdur
        hdecomp.length_in_time = hdecomp.chirp_length
        return hdecomp
コード例 #3
0
ファイル: bank.py プロジェクト: a-r-williamson/pycbc
    def get_decompressed_waveform(self, tempout, index, f_lower=None,
                                  approximant=None, df=None):
        """Returns a frequency domain decompressed waveform for the template
        in the bank corresponding to the index taken in as an argument. The
        decompressed waveform is obtained by interpolating in frequency space,
        the amplitude and phase points for the compressed template that are
        read in from the bank."""

        from pycbc.waveform.waveform import props
        from pycbc.waveform import get_waveform_filter_length_in_time

        # Get the template hash corresponding to the template index taken in as argument
        tmplt_hash = self.table.template_hash[index]

        # Read the compressed waveform from the bank file
        compressed_waveform = pycbc.waveform.compress.CompressedWaveform.from_hdf(
                                self.filehandler, tmplt_hash,
                                load_now=True)

        # Get the interpolation method to be used to decompress the waveform
        if self.waveform_decompression_method is not None :
            decompression_method = self.waveform_decompression_method
        else :
            decompression_method = compressed_waveform.interpolation
        logging.info("Decompressing waveform using %s", decompression_method)

        if df is not None :
            delta_f = df
        else :
            delta_f = self.delta_f

        # Create memory space for writing the decompressed waveform
        decomp_scratch = FrequencySeries(tempout[0:self.filter_length], delta_f=delta_f, copy=False)

        # Get the decompressed waveform
        hdecomp = compressed_waveform.decompress(out=decomp_scratch, f_lower=f_lower, interpolation=decompression_method)
        p = props(self.table[index])
        p.pop('approximant')
        try:
            tmpltdur = self.table[index].template_duration
        except AttributeError:
            tmpltdur = None
        if tmpltdur is None or tmpltdur==0.0 :
            tmpltdur = get_waveform_filter_length_in_time(approximant, **p)
        hdecomp.chirp_length = tmpltdur
        hdecomp.length_in_time = hdecomp.chirp_length
        return hdecomp
コード例 #4
0
    def __getitem__(self, index):
        if isinstance(index, slice):
            return self.getslice(index)

        approximant = self.approximant(index)
        f_end = self.end_frequency(index)
        flow = self.table[index].f_lower        

        # Determine the length of time of the filter, rounded up to
        # nearest power of two
        min_buffer = .5 + self.minimum_buffer

        from pycbc.waveform.waveform import props
        p = props(self.table[index])
        p.pop('approximant')
        buff_size = pycbc.waveform.get_waveform_filter_length_in_time(approximant, **p)
        
        tlen = self.round_up((buff_size + min_buffer) * self.sample_rate)
        flen = tlen / 2 + 1

        delta_f = self.sample_rate / float(tlen)

        if f_end is None or f_end >= (flen * delta_f):
            f_end = (flen-1) * delta_f

        logging.info("Generating %s, %ss, %i" % (approximant, 1.0/delta_f, index))

        # Get the waveform filter
        distance = 1.0 / DYN_RANGE_FAC
        htilde = pycbc.waveform.get_waveform_filter(
            zeros(flen, dtype=numpy.complex64), self.table[index],
            approximant=approximant, f_lower=flow, f_final=f_end,
            delta_f=delta_f, delta_t=1.0/self.sample_rate, distance=distance,
            **self.extra_args)

        # If available, record the total duration (which may
        # include ringdown) and the duration up to merger since they will be
        # erased by the type conversion below.
        ttotal = template_duration = -1
        if hasattr(htilde, 'length_in_time'):
                ttotal = htilde.length_in_time
        if hasattr(htilde, 'chirp_length'):
                template_duration = htilde.chirp_length

        self.table[index].template_duration = template_duration

        htilde = htilde.astype(numpy.complex64)
        htilde.f_lower = flow
        htilde.end_idx = int(htilde.f_end / htilde.delta_f)
        htilde.params = self.table[index]
        htilde.chirp_length = template_duration
        htilde.length_in_time = ttotal
        htilde.approximant = approximant
        htilde.end_frequency = f_end

        # Add sigmasq as a method of this instance
        htilde.sigmasq = types.MethodType(sigma_cached, htilde)
        htilde._sigmasq = {}

        htilde.id = self.id_from_hash(hash((htilde.params.mass1,
                                      htilde.params.mass2,
                                      htilde.params.spin1z,
                                      htilde.params.spin2z)))
        return htilde
コード例 #5
0
    def __getitem__(self, index):
        approximant = self.approximant(index)
        f_end = self.end_frequency(index)

        # Determine the length of time of the filter, rounded up to
        # nearest power of two
        min_buffer = 1.0 + self.minimum_buffer

        from pycbc.waveform.waveform import props
        buff_size = pycbc.waveform.get_waveform_filter_length_in_time(
            approximant, f_lower=self.f_lower, **props(self.table[index]))
        tlen = nearest_larger_binary_number(
            (buff_size + min_buffer) * self.sample_rate)
        flen = tlen / 2 + 1

        delta_f = self.sample_rate / float(tlen)

        if f_end is None or f_end >= (flen * delta_f):
            f_end = (flen - 1) * delta_f

        logging.info("Generating %s, %ss, %i" %
                     (approximant, 1.0 / delta_f, index))

        # Get the waveform filter
        distance = 1.0 / DYN_RANGE_FAC
        htilde = pycbc.waveform.get_waveform_filter(
            zeros(flen, dtype=numpy.complex64),
            self.table[index],
            approximant=approximant,
            f_lower=self.f_lower,
            f_final=f_end,
            delta_f=delta_f,
            delta_t=1.0 / self.sample_rate,
            distance=distance,
            **self.extra_args)

        # If available, record the total duration (which may
        # include ringdown) and the duration up to merger since they will be
        # erased by the type conversion below.
        # NOTE: If these durations are not available the values in self.table
        #       will continue to take the values in the input file.
        if hasattr(htilde, 'length_in_time'):
            if htilde.length_in_time is not None:
                self.table[index].ttotal = htilde.length_in_time
        if hasattr(htilde, 'chirp_length'):
            if htilde.chirp_length is not None:
                self.table[index].template_duration = htilde.chirp_length

        htilde = htilde.astype(numpy.complex64)
        htilde.f_lower = self.f_lower
        htilde.end_frequency = f_end
        htilde.end_idx = int(htilde.end_frequency / htilde.delta_f)
        htilde.params = self.table[index]
        htilde.approximant = approximant
        htilde.chirp_length = htilde.params.template_duration
        htilde.length_in_time = htilde.params.ttotal

        # Add sigmasq as a method of this instance
        htilde.sigmasq = types.MethodType(sigma_cached, htilde)
        htilde._sigmasq = {}

        return htilde
コード例 #6
0
def modhm_fd(**kwargs):
    r"""Allows a waveform to be generated with different parameters for the
    sub-dominant modes.

    Modified parameters may be specified in one of two ways. For parameter
    ``{parameter}`` and mode ``{mode}`` you can either provide
    ``mod_{mode}_{parameter}`` or ``fdiff_{mode}_{parameter}``. If the former,
    the given value will be used for the parameter for the given mode. If the
    latter, the parameter will be scaled by 1 + the given value for the
    specified mode.

    Special combinations of parameters are recognized. They are:

    * ``mchirp``, ``eta`` : if either of these are modified, then ``mass1``
      and ``mass2`` wil be adjusted accordingly. If the resulting ``eta``
      is unphysical (not in [0, 0.25]) or chirp mass (not > 0) is unphysical,
      a ``NoWaveformError`` is raised.
    * ``chi_eff``, ``chi_a``: if either of these are modified, then ``spin1z``
      and ``spin2z`` will be adjusted accordingly, using the modified ``mass1``
      and ``mass2``.
    * ``spin1_perp``, ``spin1_azimuthal`` : if either of these are modified,
      then ``spin1x`` and ``spin1y`` will be adjusted accordingly.
    * ``spin2_perp``, ``spin2_azimuthal``: same as above, but for the second
      object.

    If the resulting modified spins yield a magnitude > 1, a ``NoWaveformError``
    is raised.
      

    Parameters
    ----------
    base_approximant : str
        The waveform approximant to use.
    mode_array : array of tuples
        The modes to generate, e.g., ``[(2, 2), (3, 3)]``.
    fdiff_{mode}_{parameter} : float, optional
        Adjust the parameter ``{parameter}`` for mode ``{mode}`` by the
        given fractional difference.
    absdiff_{mode}_{parameter} : float, optional
        Adjust the parameter ``{parameter}`` for mode ``{mode}`` by the
        given absolute difference.
    replace_{mode}_{parameter} : float, optional
        Use the given value for ``{parameter}`` for mode ``{mode}``.
    amp_{mode} : float, optional
        Modify the amplitude of mode ``{mode}`` by the given scale factor.
    other kwargs :
        All other keyword argument are passed to
        :py:func:`pycbc.waveform.waveform.get_fd_waveform`.

    Returns
    -------
    hp : FrequencySeries
        The plus polarization.
    hc : FrequencySeries
        The cross polarization.
    """
    # pull out the base wavefrom
    try:
        apprx = kwargs.pop("base_approximant")
    except KeyError:
        raise ValueError("Must provide a base_approximant")
    try:
        mode_array = kwargs.pop("mode_array")
    except KeyError:
        raise ValueError("Must provide a mode_array")
    # ensure mode array is a list of modes
    if isinstance(mode_array, str):
        mode_array = [tuple(int(m) for m in mode)
                      for mode in shlex.split(mode_array)]
    # set the approximant to the base
    kwargs["approximant"] = apprx
    # add default values, check for other required values
    kwargs = props(None, **kwargs)
    # pull out the modification arguments
    modargs = [p for p in kwargs
               if p.startswith("fdiff_") or p.startswith("absdiff_")
               or p.startswith("replace_")]
    modargs = dict((p, kwargs.pop(p)) for p in modargs)
    # parse the parameters
    modparams = {}
    for p, val in modargs.items():
        # template is (fdiff|mod)_mode_param
        diffarg, mode, param = p.split('_', 2)
        mode = tuple(int(x) for x in mode)
        try:
            addto = modparams[mode]
        except KeyError:
            addto = modparams[mode] = {}
        if param in addto:
            # the parameter is already there; means multiple args were given
            raise ValueError("Provide only one of absdiff_{m}_{p}, "
                             "fdiff_{m}_{p}, or replace_{m}_{p}".format(
                             m=''.join(map(str, mode)), p=param))
        addto[param] = (val, diffarg)
    # cycle over the modes, generating the waveform one at a time
    hps = []
    hcs = []
    wfargs = kwargs.copy()
    size = 0
    for mode in mode_array:
        # make sure mode is a tuple
        mode = tuple(mode)
        if mode in modparams:
            # convert mchirp, eta to mass1, mass2 if they are provided
            mchirp_mod = modparams[mode].pop('mchirp', None)
            eta_mod = modparams[mode].pop('eta', None)
            if mchirp_mod is not None or eta_mod is not None:
                m1, m2 = transform_masses(kwargs['mass1'], kwargs['mass2'],
                                          mchirp_mod, eta_mod)
                wfargs['mass1'] = m1
                wfargs['mass2'] = m2
            # convert spins
            chieff_mod = modparams[mode].pop('chi_eff', None)
            chia_mod = modparams[mode].pop('chi_a', None)
            if chieff_mod is not None or chia_mod is not None:
                s1z, s2z = transform_spinzs(wfargs['mass1'], wfargs['mass2'],
                                            kwargs['spin1z'], kwargs['spin2z'],
                                            chieff_mod, chia_mod)
                wfargs['spin1z'] = s1z
                wfargs['spin2z'] = s2z
            spin1_perp_mod = modparams[mode].pop('spin1_perp', None)
            spin1_az_mod = modparams[mode].pop('spin1_azimuthal', None)
            if spin1_perp_mod is not None or spin1_az_mod is not None:
                s1x, s1y = transform_spin_perp(kwargs['spin1x'],
                                               kwargs['spin1y'],
                                               spin1_perp_mod, spin1_az_mod)
                wfargs['spin1x'] = s1x
                wfargs['spin1y'] = s1y
            spin2_perp_mod = modparams[mode].pop('spin2_perp', None)
            spin2_az_mod = modparams[mode].pop('spin2_azimuthal', None)
            if spin2_perp_mod is not None or spin2_az_mod is not None:
                s2x, s2y = transform_spin_perp(kwargs['spin2x'],
                                               kwargs['spin2y'],
                                               spin2_perp_mod, spin2_az_mod)
                wfargs['spin2x'] = s2x
                wfargs['spin2y'] = s2y
            # update all other parameters
            for p in list(modparams[mode].keys()):
                diff, modtype = modparams[mode].pop(p)
                wfargs[p] = apply_mod(kwargs[p], diff, modtype)
            # check that we still have physical spins
            for obj in [1, 2]:
                mag = (wfargs['spin{}x'.format(obj)]**2 +
                       wfargs['spin{}y'.format(obj)]**2 +
                       wfargs['spin{}z'.format(obj)]**2)**0.5
                if mag >= 1:
                    raise NoWaveformError("unphysical spins")
        wfargs['mode_array'] = [mode]
        # pull out any amplitude scaling
        scalefac = wfargs.pop('amp_{}'.format(''.join(map(str, mode))), 1.)
        hp, hc = get_fd_waveform(**wfargs) 
        if scalefac != 1.:
            hp *= scalefac
            hc *= scalefac
        hps.append(hp)
        hcs.append(hc)
        size = max(size, len(hp))
    # make sure everything is the same size
    for ii, hp in enumerate(hps):
        hp.resize(size)
        hcs[ii].resize(size)
    return sum(hps), sum(hcs)