def fftgram(timeseries, stride, pad=False): """ calculates fourier-gram with automatic 50% overlapping hann windowing. Parameters ---------- timeseries : gwpy TimeSeries time series to take fftgram of stride : `int` number of seconds in single PSD Returns ------- fftgram : gwpy spectrogram a fourier-gram """ fftlength = stride dt = stride df = 1. / fftlength # number of values in a step stride *= timeseries.sample_rate.value # number of steps nsteps = 2 * int(timeseries.size // stride) - 1 # only get positive frequencies if pad: nfreqs = int(fftlength * timeseries.sample_rate.value) df = df / 2 f0 = df else: nfreqs = int(fftlength * timeseries.sample_rate.value) / 2 dtype = np.complex # initialize the spectrogram out = Spectrogram(np.zeros((nsteps, nfreqs), dtype=dtype), name=timeseries.name, epoch=timeseries.epoch, f0=df, df=df, dt=dt, copy=True, unit=1 / u.Hz**0.5, dtype=dtype) # stride through TimeSeries, recording FFTs as columns of Spectrogram for step in range(nsteps): # indexes for this step idx = (stride / 2) * step idx_end = idx + stride stepseries = timeseries[idx:idx_end] # zeropad, window, fft, shift zero to center, normalize # window stepseries = np.multiply(stepseries, np.hanning(stepseries.value.size)) # take fft if pad: stepseries = TimeSeries(np.hstack((stepseries, np.zeros(stepseries.size))), name=stepseries.name, x0=stepseries.x0, dx=timeseries.dx) tempfft = stepseries.fft(stepseries.size) else: tempfft = stepseries.fft(stepseries.size) tempfft.override_unit(out.unit) out[step] = tempfft[1:] return out
noise, then inject a loud, steady sinuosoid. We will do this in the frequency domain because it is much easier to model a sinusoid there. """ __author__ = "Alex Urban <*****@*****.**>" __currentmodule__ = 'gwpy.timeseries' # First, we prepare one second of Gaussian noise: from numpy import random from gwpy.timeseries import TimeSeries noise = TimeSeries(random.normal(scale=.1, size=1024), sample_rate=1024) # To inject a signal in the frequency domain, we need to take an FFT: noisefd = noise.fft() # We can now easily inject a loud sinusoid of unit amplitude at, say, # 30 Hz. To do this, we use :meth:`~gwpy.types.series.Series.inject`. import numpy from gwpy.frequencyseries import FrequencySeries signal = FrequencySeries(numpy.array([1.]), f0=30, df=noisefd.df) injfd = noisefd.inject(signal) # We can then visualize the data before and after injection in the frequency # domain: from gwpy.plot import Plot plot = Plot(numpy.abs(noisefd), numpy.abs(injfd),
def test_ifft(self): # construct a TimeSeries, then check that it is unchanged by # the operation TimeSeries.fft().ifft() ts = TimeSeries([1.0, 0.0, -1.0, 0.0], sample_rate=1.0) assert ts.fft().ifft() == ts utils.assert_allclose(ts.fft().ifft().value, ts.value)
noise, then inject a loud, steady sinuosoid. We will do this in the frequency domain because it is much easier to model a sinusoid there. """ __author__ = "Alex Urban <*****@*****.**>" __currentmodule__ = 'gwpy.timeseries' # First, we prepare one second of Gaussian noise: from numpy import random from gwpy.timeseries import TimeSeries noise = TimeSeries(random.normal(scale=.1, size=1024), sample_rate=1024) # To inject a signal in the frequency domain, we need to take an FFT: noisefd = noise.fft() # We can now easily inject a loud sinusoid of unit amplitude at, say, # 30 Hz. To do this, we use :meth:`~gwpy.types.series.Series.inject`. import numpy from gwpy.frequencyseries import FrequencySeries signal = FrequencySeries(numpy.array([1.]), f0=30, df=noisefd.df) injfd = noisefd.inject(signal) # We can then visualize the data before and after injection in the frequency # domain: from gwpy.plot import Plot plot = Plot(numpy.abs(noisefd), numpy.abs(injfd), separate=True, sharex=True, sharey=True, xscale='log', yscale='log')
def fftgram(timeseries, stride, overlap=None, pad=False): """ calculates fourier-gram with auto 50% overlapping segments and hann windowed Parameters ---------- timeseries : gwpy TimeSeries time series to take fftgram of stride : `int` number of seconds in single PSD overalp : `int` number of seconds of overlap Returns ------- fftgram : gwpy spectrogram a fourier-gram """ fftlength = stride if not overlap: overlap = stride / 2. dt = stride - overlap df = 1. / fftlength # number of values in a step stride *= timeseries.sample_rate.value overlap *= timeseries.sample_rate.value step = stride - overlap # number of steps nsteps = int(timeseries.size // step) - 1 # only get positive frequencies if pad: nfreqs = int(fftlength * timeseries.sample_rate.value) df = df / 2 f0 = df else: nfreqs = int(fftlength * timeseries.sample_rate.value) / 2 dtype = np.complex # initialize the spectrogram out = Spectrogram(np.zeros((nsteps, nfreqs), dtype=dtype), name=timeseries.name, epoch=timeseries.epoch, f0=df, df=df, dt=dt, copy=True, unit=1 / u.Hz**0.5, dtype=dtype) # stride through TimeSeries, recording FFTs as columns of Spectrogram if (timeseries.sample_rate.value * stride) % 1: raise ValueError('1 / stride must evenly divide sample rate of channel') for step in range(nsteps): # indexes for this step idx = (stride / 2) * step idx_end = idx + stride stepseries = timeseries[idx:idx_end] # zeropad, window, fft stepseries = np.multiply(stepseries, np.hanning(stepseries.value.size)) # hann windowing normalization norm = np.sum(np.hanning(stepseries.value.size)) if pad: stepseries = TimeSeries(np.hstack((stepseries, np.zeros(stepseries.size))), name=stepseries.name, x0=stepseries.x0, dx=timeseries.dx) tempfft = stepseries.fft(stepseries.size) else: tempfft = stepseries.fft(stepseries.size) # reset proper unit tempfft.override_unit(out.unit) # normalize out[step] = tempfft[1:] / norm return out
def test_ifft(self): # construct a TimeSeries, then check that it is unchanged by # the operation TimeSeries.fft().ifft() ts = TimeSeries([1.0, 0.0, -1.0, 0.0], sample_rate=1.0) assert ts.fft().ifft() == ts utils.assert_allclose(ts.fft().ifft().value, ts.value)
def fftgram(timeseries, stride, pad=False): """ calculates fourier-gram with automatic 50% overlapping hann windowing. Parameters ---------- timeseries : gwpy TimeSeries time series to take fftgram of stride : `int` number of seconds in single PSD Returns ------- fftgram : gwpy spectrogram a fourier-gram """ fftlength = stride dt = stride df = 1. / fftlength # number of values in a step stride *= timeseries.sample_rate.value # number of steps nsteps = 2 * int(timeseries.size // stride) - 1 # only get positive frequencies if pad: nfreqs = int(fftlength * timeseries.sample_rate.value) df = df / 2 f0 = df else: nfreqs = int(fftlength * timeseries.sample_rate.value) / 2 dtype = np.complex # initialize the spectrogram out = Spectrogram(np.zeros((nsteps, nfreqs), dtype=dtype), name=timeseries.name, epoch=timeseries.epoch, f0=df, df=df, dt=dt, copy=True, unit=1 / u.Hz**0.5, dtype=dtype) # stride through TimeSeries, recording FFTs as columns of Spectrogram for step in range(nsteps): # indexes for this step idx = (stride / 2) * step idx_end = idx + stride stepseries = timeseries[idx:idx_end] # zeropad, window, fft, shift zero to center, normalize # window stepseries = np.multiply(stepseries, np.hanning(stepseries.value.size)) # take fft if pad: stepseries = TimeSeries(np.hstack( (stepseries, np.zeros(stepseries.size))), name=stepseries.name, x0=stepseries.x0, dx=timeseries.dx) tempfft = stepseries.fft(stepseries.size) else: tempfft = stepseries.fft(stepseries.size) tempfft.override_unit(out.unit) out[step] = tempfft[1:] return out
def fftgram(timeseries, stride, overlap=None, pad=False): """ calculates fourier-gram with auto 50% overlapping segments and hann windowed Parameters ---------- timeseries : :py:mod:`gwpy.timeseries.TimeSeries` time series to take fftgram of stride : `int` number of seconds in single PSD overalp : `int` number of seconds of overlap. Defaults to half of stride. Returns ------- fftgram : :py:mod:`gwpy.spectrogram.Spectrogram` a fourier-gram """ fftlength = stride if overlap is None: overlap = stride / 2. dt = stride - overlap df = 1. / fftlength # number of values in a step stride *= timeseries.sample_rate.value overlap *= timeseries.sample_rate.value step = stride - overlap # number of steps nsteps = int(timeseries.size // step) - 1 # only get positive frequencies if pad: nfreqs = int(fftlength * timeseries.sample_rate.value) df = df / 2 f0 = df else: nfreqs = int(fftlength * timeseries.sample_rate.value) / 2 dtype = np.complex # initialize the spectrogram out = Spectrogram(np.zeros((nsteps, nfreqs), dtype=dtype), name=timeseries.name, epoch=timeseries.epoch, f0=df, df=df, dt=dt, copy=True, unit=u.Hz**(-0.5), dtype=dtype) # stride through TimeSeries, recording FFTs as columns of Spectrogram if (timeseries.sample_rate.value * stride) % 1: raise ValueError('1/stride must evenly divide sample rate of channel') for step in range(nsteps): # indexes for this step idx = int((stride / 2) * step) idx_end = int(idx + stride) stepseries = timeseries[idx:idx_end] # zeropad, window, fft stepseries = np.multiply(stepseries, np.hanning(stepseries.value.size)) # hann windowing normalization norm = np.sum(np.hanning(stepseries.value.size)) if pad: stepseries = TimeSeries(np.hstack( (stepseries, np.zeros(stepseries.size))), name=stepseries.name, x0=stepseries.x0, dx=timeseries.dx) tempfft = stepseries.fft(stepseries.size) else: tempfft = stepseries.fft(stepseries.size) # reset proper unit tempfft.override_unit(out.unit) # normalize out[step] = tempfft[1:] / norm return out