如何在Python中生成0-60Hz带宽的时域随机信号?
生成0-60Hz带宽的时域随机信号(Python实现)
作为Python新手,你可以通过两种实操方案实现需求:频域构造+逆傅里叶变换(精准控制带宽)或白噪声加低通滤波(简单易上手),下面是具体实现:
方案一:频域构造法(严格控制带宽)
直接在频域生成符合带宽要求的随机频谱,再转换为时域信号,能精准限定0-60Hz的频率范围。
代码实现
import numpy as np import matplotlib.pyplot as plt # 设置核心参数 sampling_rate = 200 # 采样率需大于120Hz(60*2,满足奈奎斯特准则) duration = 5 # 信号时长(秒) n_samples = sampling_rate * duration # 总采样点数 freqs = np.fft.fftfreq(n_samples, 1/sampling_rate) # 生成频率轴 # 构造频域随机信号 mask = (freqs >= 0) & (freqs <= 60) # 仅保留0-60Hz的频率分量 amp = np.random.normal(0, 1, n_samples) # 生成正态分布随机幅值 phase = np.random.uniform(0, 2*np.pi, n_samples) # 生成随机相位 freq_signal = amp * np.exp(1j * phase) # 频域信号=幅值*复指数 freq_signal[~mask] = 0 # 清除60Hz以上的分量 freq_signal = freq_signal + freq_signal.conj()[::-1] # 共轭对称保证时域信号为实数 # 逆傅里叶变换得到时域信号 time_signal = np.fft.ifft(freq_signal).real # 验证频谱(可选) freq_response = np.fft.fft(time_signal) amplitude_spectrum = np.abs(freq_response) / n_samples # 绘图展示 plt.figure(figsize=(12,6)) plt.subplot(2,1,1) plt.plot(np.arange(n_samples)/sampling_rate, time_signal) plt.title('时域随机信号') plt.xlabel('时间(秒)') plt.ylabel('幅值') plt.subplot(2,1,2) plt.plot(freqs[:n_samples//2], amplitude_spectrum[:n_samples//2]) plt.title('频谱(0-60Hz)') plt.xlabel('频率(Hz)') plt.ylabel('幅值') plt.xlim(0, 100) # 显示到100Hz,验证60Hz以上无有效分量 plt.tight_layout() plt.show()
方案二:白噪声加低通滤波(快速上手)
先生成无规则白噪声,再用低通滤波器滤除60Hz以上的分量,适合新手快速理解。
代码实现
import numpy as np import matplotlib.pyplot as plt from scipy.signal import butter, filtfilt # 设置参数 sampling_rate = 200 duration = 5 n_samples = sampling_rate * duration # 生成白噪声 white_noise = np.random.normal(0, 1, n_samples) # 设计60Hz低通滤波器 def butter_lowpass(cutoff, fs, order=5): nyq = 0.5 * fs normal_cutoff = cutoff / nyq b, a = butter(order, normal_cutoff, btype='low', analog=False) return b, a # 应用零相位滤波(避免信号相位偏移) b, a = butter_lowpass(60, sampling_rate, order=4) filtered_signal = filtfilt(b, a, white_noise) # 绘图验证 plt.figure(figsize=(12,6)) plt.subplot(2,1,1) plt.plot(np.arange(n_samples)/sampling_rate, filtered_signal) plt.title('滤波后的时域随机信号') plt.xlabel('时间(秒)') plt.subplot(2,1,2) freqs = np.fft.fftfreq(n_samples, 1/sampling_rate) spectrum = np.abs(np.fft.fft(filtered_signal)) / n_samples plt.plot(freqs[:n_samples//2], spectrum[:n_samples//2]) plt.title('滤波后频谱') plt.xlabel('频率(Hz)') plt.xlim(0, 100) plt.tight_layout() plt.show()
关键提示
- 采样率必须大于带宽上限的2倍,否则会出现混叠失真,导致频域分量异常。
- 频域构造法能严格截断60Hz以上的分量,滤波法会有轻微过渡带(60Hz附近信号不会完全消失),按需选择即可。
内容的提问来源于stack exchange,提问作者Mehdi Zakaria
相关产品推荐
相关产品推荐

