def _create_powerlaw(n_samples, fs, exponent): """Create a power law time series. Parameters ---------- n_samples : int The number of samples to simulate. fs : float Sampling rate of simulated signal, in Hz. exponent : float Desired power-law exponent, of the form P(f)=f^exponent. Returns ------- sig: 1d array Time-series with the desired power law exponent. Notes ----- This function creates variable power law exponents by spectrally rotating white noise. """ # Start with white noise signal, that we will rotate, in frequency space sig = np.random.randn(n_samples) # Compute the FFT fft_output = np.fft.fft(sig) freqs = np.fft.fftfreq(len(sig), 1. / fs) # Rotate spectrum and invert back to time series, with a z-score to normalize # Delta exponent is divided by two, as the FFT output is in units of amplitude not power fft_output_rot = rotate_powerlaw(freqs, fft_output, -exponent / 2) sig = zscore(np.real(np.fft.ifft(fft_output_rot))) return sig
def sim_powerlaw(n_seconds, fs, exponent=-2.0, f_range=None, **filter_kwargs): """Generate a power law time series with specified exponent by spectrally rotating white noise. Parameters ---------- n_seconds : float Simulation time, in seconds. fs : float Sampling rate of simulated signal, in Hz. exponent : float Desired power-law exponent, of the form P(f)=f^exponent. f_range : list of [float, float] or None, optional Frequency range to filter simulated data, as [f_lo, f_hi], in Hz. **filter_kwargs : kwargs, optional Keyword arguments to pass to `filter_signal`. Returns ------- sig: 1d array Time-series with the desired power-law exponent. """ n_samples = int(n_seconds * fs) sig = np.random.randn(n_samples) # Compute the FFT fft_output = np.fft.fft(sig) freqs = np.fft.fftfreq(len(sig), 1. / fs) # Rotate spectrum and invert, zscore to normalize. # Note: the delta exponent to be applied is divided by two, as # the FFT output is in units of amplitude not power fft_output_rot = rotate_powerlaw(freqs, fft_output, -exponent/2) sig = zscore(np.real(np.fft.ifft(fft_output_rot))) if f_range is not None: filter_signal(sig, fs, infer_passtype(f_range), f_range, **filter_kwargs) return sig
################################################################################################### # Spectral Rotation # ----------------- # # Another included utility function is spectral rotation, which rotates the power # spectrum about a given axis frequency, by an amount indicated by the 'delta_exponent' # argument (negative is clockwise, positive is counterclockwise). # # You can perform spectral rotation with # :func:`~neurodsp.spectral.utils.rotate_powerlaw`. # # # This function is mostly useful for investigating the effect of rotating the spectrum # in frequency domain on the time domain signal. Effectively, this performs a very specific # type of filtering with an ultra long filter kernel. # ################################################################################################### psd_rot = spectral.rotate_powerlaw(freq_med, psd_med, delta_exponent=-1, f_rotation=35) plot_power_spectra([freq_med[:200], freq_med[:200]], [psd_med[:200], psd_rot[:200]], ['Original', 'Rotated']) ################################################################################################### # # Sphinx settings: # sphinx_gallery_thumbnail_number = 2 #