Python 并行短时傅里叶变换(频谱分析);懒洋洋地使用Xarray(和/或Dask) 问题:

Python 并行短时傅里叶变换(频谱分析);懒洋洋地使用Xarray(和/或Dask) 问题:,python,scipy,dask,python-xarray,Python,Scipy,Dask,Python Xarray,我试图对长时间序列数据进行频谱分析(数据结构见示例,它基本上是带时间索引的一维数据)。为了节省时间和内存等,我希望并行和惰性地(使用xarray和/或dask)执行此操作。 最好(或更好)的方法是什么 我的尝试: (示例和代码见下文) 使用scipy.signal.stft和xr.apply\u ufunc: 问题:ValueError,仅在输入数据为1个区块时有效,这不适用于大数据 将scipy.signal.stft与dask.array.from_delayed一起使用: 问题:输出数据

我试图对长时间序列数据进行频谱分析(数据结构见示例,它基本上是带时间索引的一维数据)。为了节省时间和内存等,我希望并行和惰性地(使用xarray和/或dask)执行此操作。
最好(或更好)的方法是什么

我的尝试: (示例和代码见下文)

  • 使用scipy.signal.stft和xr.apply\u ufunc:
    问题:ValueError,仅在输入数据为1个区块时有效,这不适用于大数据

  • 将scipy.signal.stft与dask.array.from_delayed一起使用:
    问题:输出数据总是一个块,这使得进一步处理数据变得困难。(之后重新锁定会使RAM过载)

  • 使用xr.Dataset.rolling.construct进行中间(延迟)二维变换。这里一维是时间,行是我做fft的短时间窗口(“滚动窗口”)

    使用数据:[1,2,3,4,5]和滚动窗口3,这将成为:

    时间索引 滚动窗口 00:00:00 楠楠1 00:00:01 南,1,2 00:00:02 1, 2, 3 00:00:03 2, 3, 4 00:00:04 3, 4, 5
    好的,我终于找到了一种在大数据集上工作的方法:
    (工作代码如下)

    要使方法3在大型数据集上工作,请确保调整使用2d转换创建的(大得多)块的块大小(本例中为1.31 TB,数据长度为128e7):

    在我的系统(16GB RAM)上使用示例中的参数,24000块是最佳的(245.76MB)。最佳块大小可以随频率和窗口的不同而变化

    工作代码:

    def xr_make_fft(ds, par):
        ds['roll_window'] = np.arange(window)  # create dimension for rolling window
        
        # FFT function to apply vectorized:
        def xr_fft(x):
            fft = np.fft.fft(x)[xr_fft.idx]
            return np.abs(fft)
        
        # make new parameter with rolling windows stacked
        ds['FFT_window'] = ds[par].rolling(dim_0=window).construct("roll_window",).chunk({'dim_0': 24000})
        
        # Calc FFT Freq domain
        fftfreq = np.fft.fftfreq(window, 1 / fs)
        idx = (0 < fftfreq)
        freq = fftfreq[idx]
        ds['Frequency'] = freq
        xr_fft.idx = idx
        
        ds[f'FFT'] = xr.apply_ufunc(xr_fft,
                                    ds[f"FFT_window"],
                                    vectorize=True,
                                    input_core_dims=[["roll_window"]],  # define input dim over which to vectorize (this dim in inserted completely)
                                    output_core_dims=[["Frequency"]],   # define newly created output dims
                                    dask="parallelized",
                                    output_dtypes=['f8'],
                                    output_sizes={"Frequency": len(freq)},
                                    )
        
        ds = ds.drop(f'FFT_window').drop_dims('roll_window')
        return ds
    
    data = xr_make_fft(data, "x")
    
    def xr_make_fft(ds,par):
    ds['roll_window']=np.arange(window)#为滚动窗口创建尺寸
    #应用矢量化的FFT函数:
    def xr_fft(x):
    fft=np.fft.fft(x)[xr_fft.idx]
    返回np.abs(fft)
    #使用堆叠的滚动窗口创建新参数
    ds['FFT_window']=ds[par]。滚动(dim_0=window)。构造(“滚动窗口”)。块({'dim_0':24000})
    #计算FFT频域
    fftfreq=np.fft.fftfreq(窗口,1/fs)
    idx=(0
    我觉得还有优化的空间,所以如果你有建议,请在这里发布:)