Ejemplo n.º 1
0
def compress_waveform(htilde,
                      sample_points,
                      tolerance,
                      interpolation,
                      precision,
                      decomp_scratch=None,
                      psd=None):
    """Retrieves the amplitude and phase at the desired sample points, and adds
    frequency points in order to ensure that the interpolated waveform
    has a mismatch with the full waveform that is <= the desired tolerance. The
    mismatch is computed by finding 1-overlap between `htilde` and the
    decompressed waveform; no maximimization over phase/time is done, a
    PSD may be used.

    .. note::
        The decompressed waveform is only garaunteed to have a true mismatch
        <= the tolerance for the given `interpolation` and for no PSD.
        However, since no maximization over time/phase is performed when
        adding points, the actual mismatch between the decompressed waveform
        and `htilde` is better than the tolerance, using no PSD. Using a PSD
        does increase the mismatch, and can lead to mismatches > than the
        desired tolerance, but typically by only a factor of a few worse.

    Parameters
    ----------
    htilde : FrequencySeries
        The waveform to compress.
    sample_points : array
        The frequencies at which to store the amplitude and phase. More points
        may be added to this, depending on the desired tolerance.
    tolerance : float
        The maximum mismatch to allow between a decompressed waveform and
        `htilde`.
    interpolation : str
        The interpolation to use for decompressing the waveform when computing
        overlaps.
    precision : str
        The precision being used to generate and store the compressed waveform
        points.
    decomp_scratch : {None, FrequencySeries}
        Optionally provide scratch space for decompressing the waveform. The
        provided frequency series must have the same `delta_f` and length
        as `htilde`.
    psd : {None, FrequencySeries}
        The psd to use for calculating the overlap between the decompressed
        waveform and the original full waveform.

    Returns
    -------
    CompressedWaveform
        The compressed waveform data; see `CompressedWaveform` for details.
    """
    fmin = sample_points.min()
    df = htilde.delta_f
    sample_index = (sample_points / df).astype(int)
    amp = utils.amplitude_from_frequencyseries(htilde)
    phase = utils.phase_from_frequencyseries(htilde)

    comp_amp = amp.take(sample_index)
    comp_phase = phase.take(sample_index)
    if decomp_scratch is None:
        outdf = df
    else:
        outdf = None
    hdecomp = fd_decompress(comp_amp,
                            comp_phase,
                            sample_points,
                            out=decomp_scratch,
                            df=outdf,
                            f_lower=fmin,
                            interpolation=interpolation)
    kmax = min(len(htilde), len(hdecomp))
    htilde = htilde[:kmax]
    hdecomp = hdecomp[:kmax]
    mismatch = 1. - filter.overlap(
        hdecomp, htilde, psd=psd, low_frequency_cutoff=fmin)
    if mismatch > tolerance:
        # we'll need the difference in the waveforms as a function of frequency
        vecdiffs = vecdiff(htilde, hdecomp, sample_points, psd=psd)

    # We will find where in the frequency series the interpolated waveform
    # has the smallest overlap with the full waveform, add a sample point
    # there, and re-interpolate. We repeat this until the overall mismatch
    # is > than the desired tolerance
    added_points = []
    while mismatch > tolerance:
        minpt = vecdiffs.argmax()
        # add a point at the frequency halfway between minpt and minpt+1
        add_freq = sample_points[[minpt, minpt + 1]].mean()
        addidx = int(round(add_freq / df))
        # ensure that only new points are added
        if addidx in sample_index:
            diffidx = vecdiffs.argsort()
            addpt = -1
            while addidx in sample_index:
                addpt -= 1
                try:
                    minpt = diffidx[addpt]
                except IndexError:
                    raise ValueError("unable to compress to desired tolerance")
                add_freq = sample_points[[minpt, minpt + 1]].mean()
                addidx = int(round(add_freq / df))
        new_index = numpy.zeros(sample_index.size + 1, dtype=int)
        new_index[:minpt + 1] = sample_index[:minpt + 1]
        new_index[minpt + 1] = addidx
        new_index[minpt + 2:] = sample_index[minpt + 1:]
        sample_index = new_index
        sample_points = (sample_index * df).astype(
            real_same_precision_as(htilde))
        # get the new compressed points
        comp_amp = amp.take(sample_index)
        comp_phase = phase.take(sample_index)
        # update the vecdiffs and mismatch
        hdecomp = fd_decompress(comp_amp,
                                comp_phase,
                                sample_points,
                                out=decomp_scratch,
                                df=outdf,
                                f_lower=fmin,
                                interpolation=interpolation)
        hdecomp = hdecomp[:kmax]
        new_vecdiffs = numpy.zeros(vecdiffs.size + 1)
        new_vecdiffs[:minpt] = vecdiffs[:minpt]
        new_vecdiffs[minpt + 2:] = vecdiffs[minpt + 1:]
        new_vecdiffs[minpt:minpt + 2] = vecdiff(htilde,
                                                hdecomp,
                                                sample_points[minpt:minpt + 2],
                                                psd=psd)
        vecdiffs = new_vecdiffs
        mismatch = 1. - filter.overlap(
            hdecomp, htilde, psd=psd, low_frequency_cutoff=fmin)
        added_points.append(addidx)
    logging.info("mismatch: %f, N points: %i (%i added)" %
                 (mismatch, len(comp_amp), len(added_points)))

    return CompressedWaveform(sample_points,
                              comp_amp,
                              comp_phase,
                              interpolation=interpolation,
                              tolerance=tolerance,
                              mismatch=mismatch,
                              precision=precision)
Ejemplo n.º 2
0
def compress_waveform(htilde, sample_points, tolerance, interpolation,
        decomp_scratch=None):
    """Retrieves the amplitude and phase at the desired sample points, and adds
    frequency points in order to ensure that the interpolated waveform
    has a mismatch with the full waveform that is <= the desired tolerance. The
    mismatch is computed by finding 1-overlap between `htilde` and the
    decompressed waveform; no maximimization over phase/time is done, nor is
    any PSD used.
    
    .. note::
        The decompressed waveform is only garaunteed to have a true mismatch
        <= the tolerance for the given `interpolation` and for no PSD.
        However, since no maximization over time/phase is performed when
        adding points, the actual mismatch between the decompressed waveform
        and `htilde` is better than the tolerance, using no PSD. Using a PSD
        does increase the mismatch, and can lead to mismatches > than the
        desired tolerance, but typically by only a factor of a few worse.

    Parameters
    ----------
    htilde : FrequencySeries
        The waveform to compress.
    sample_points : array
        The frequencies at which to store the amplitude and phase. More points
        may be added to this, depending on the desired tolerance.
    tolerance : float
        The maximum mismatch to allow between a decompressed waveform and
        `htilde`.
    interpolation : str
        The interpolation to use for decompressing the waveform when computing
        overlaps.
    decomp_scratch : {None, FrequencySeries}
        Optionally provide scratch space for decompressing the waveform. The
        provided frequency series must have the same `delta_f` and length
        as `htilde`.

    Returns
    -------
    CompressedWaveform
        The compressed waveform data; see `CompressedWaveform` for details.
    """
    fmin = sample_points.min()
    df = htilde.delta_f
    sample_index = (sample_points / df).astype(int)
    amp = utils.amplitude_from_frequencyseries(htilde)
    phase = utils.phase_from_frequencyseries(htilde)

    comp_amp = amp.take(sample_index)
    comp_phase = phase.take(sample_index)
    if decomp_scratch is None:
        outdf = df
    else:
        outdf = None
    out = decomp_scratch
    hdecomp = fd_decompress(comp_amp, comp_phase, sample_points,
        out=decomp_scratch, df=outdf, f_lower=fmin,
        interpolation=interpolation)
    mismatch = 1. - filter.overlap(hdecomp, htilde, low_frequency_cutoff=fmin)
    if mismatch > tolerance:
        # we'll need the difference in the waveforms as a function of frequency
        vecdiffs = vecdiff(htilde, hdecomp, sample_points)

    # We will find where in the frequency series the interpolated waveform
    # has the smallest overlap with the full waveform, add a sample point
    # there, and re-interpolate. We repeat this until the overall mismatch
    # is > than the desired tolerance 
    added_points = []
    while mismatch > tolerance:
        minpt = vecdiffs.argmax()
        # add a point at the frequency halfway between minpt and minpt+1
        add_freq = sample_points[[minpt, minpt+1]].mean()
        addidx = int(add_freq/df)
        new_index = numpy.zeros(sample_index.size+1, dtype=int)
        new_index[:minpt+1] = sample_index[:minpt+1]
        new_index[minpt+1] = addidx
        new_index[minpt+2:] = sample_index[minpt+1:]
        sample_index = new_index
        sample_points = (sample_index * df).astype(
            real_same_precision_as(htilde))
        # get the new compressed points
        comp_amp = amp.take(sample_index)
        comp_phase = phase.take(sample_index)
        # update the vecdiffs and mismatch
        hdecomp = fd_decompress(comp_amp, comp_phase, sample_points,
            out=decomp_scratch, df=outdf, f_lower=fmin,
            interpolation=interpolation)
        new_vecdiffs = numpy.zeros(vecdiffs.size+1)
        new_vecdiffs[:minpt] = vecdiffs[:minpt]
        new_vecdiffs[minpt+2:] = vecdiffs[minpt+1:]
        new_vecdiffs[minpt:minpt+2] = vecdiff(htilde, hdecomp,
            sample_points[minpt:minpt+2])
        vecdiffs = new_vecdiffs
        mismatch = 1. - filter.overlap(hdecomp, htilde,
            low_frequency_cutoff=fmin)
        added_points.append(addidx)
    logging.info("mismatch: %f, N points: %i (%i added)" %(mismatch,
        len(comp_amp), len(added_points)))
    
    return CompressedWaveform(sample_points, comp_amp, comp_phase,
                interpolation=interpolation, tolerance=tolerance,
                mismatch=mismatch)