def sim_powerlaw(n_seconds, fs, exponent=-2.0, f_range=None, **filter_kwargs): """Simulate a power law time series, with a specified exponent. Parameters ---------- n_seconds : float Simulation time, in seconds. fs : float Sampling rate of simulated signal, in Hz. exponent : float, optional, default: -2 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. """ # Get the number of samples to simulate for the signal # If filter is to be filtered, with FIR, add extra to compensate for edges if f_range and filter_kwargs.get('filter_type', None) != 'iir': pass_type = infer_passtype(f_range) filt_len = compute_filter_length(fs, pass_type, *check_filter_definition(pass_type, f_range), n_seconds=filter_kwargs.get('n_seconds', None), n_cycles=filter_kwargs.get('n_cycles', 3)) n_samples = int(n_seconds * fs) + filt_len + 1 else: n_samples = int(n_seconds * fs) sig = _create_powerlaw(n_samples, fs, exponent) if f_range is not None: sig = filter_signal(sig, fs, infer_passtype(f_range), f_range, remove_edges=True, **filter_kwargs) # Drop the edges, that were compensated for, if not using IIR (using FIR) if not filter_kwargs.get('filter_type', None) == 'iir': sig, _ = remove_nans(sig) 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
def sim_powerlaw(n_seconds, fs, exponent=-2.0, f_range=None, **filter_kwargs): """Simulate a power law time series, with a specified exponent. Parameters ---------- n_seconds : float Simulation time, in seconds. fs : float Sampling rate of simulated signal, in Hz. exponent : float, optional, default: -2 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. Notes ----- - Powerlaw data with exponents is created by spectrally rotating white noise [1]_. References ---------- .. [1] Timmer, J., & Konig, M. (1995). On Generating Power Law Noise. Astronomy and Astrophysics, 300, 707–710. Examples -------- Simulate a power law signal, with an exponent of -2 (brown noise): >>> sig = sim_powerlaw(n_seconds=1, fs=500, exponent=-2.0) Simulate a power law signal, with a highpass filter applied at 2 Hz: >>> sig = sim_powerlaw(n_seconds=1, fs=500, exponent=-1.5, f_range=(2, None)) """ # Compute the number of samples for the simulated time series n_samples = compute_nsamples(n_seconds, fs) # Get the number of samples to simulate for the signal # If signal is to be filtered, with FIR, add extra to compensate for edges if f_range and filter_kwargs.get('filter_type', None) != 'iir': pass_type = infer_passtype(f_range) filt_len = compute_filter_length( fs, pass_type, *check_filter_definition(pass_type, f_range), n_seconds=filter_kwargs.get('n_seconds', None), n_cycles=filter_kwargs.get('n_cycles', 3)) n_samples += filt_len + 1 # Simulate the powerlaw data sig = _create_powerlaw(n_samples, fs, exponent) if f_range is not None: sig = filter_signal(sig, fs, infer_passtype(f_range), f_range, remove_edges=True, **filter_kwargs) # Drop the edges, that were compensated for, if not using FIR filter if not filter_kwargs.get('filter_type', None) == 'iir': sig, _ = remove_nans(sig) return sig