Understanding scipy deconvolve

前端 未结 2 1020
无人共我
无人共我 2020-12-02 23:39

I\'m trying to understand scipy.signal.deconvolve.

From the mathematical point of view a convolution is just the multiplication in fourier space so I would expect

相关标签:
2条回答
  • 2020-12-03 00:01

    As written in the comments, I cannot help with the example you posted originally. As @Stelios has pointed out, the deconvolution might not work out due to numerical issues.

    I can, however, reproduce the example you posted in your Edit:

    That is the code which is a direct translation from the matlab source code:

    import numpy as np
    import scipy.signal
    import matplotlib.pyplot as plt
    
    x = np.arange(0., 20.01, 0.01)
    y = np.zeros(len(x))
    y[900:1100] = 1.
    y += 0.01 * np.random.randn(len(y))
    c = np.exp(-(np.arange(len(y))) / 30.)
    
    yc = scipy.signal.convolve(y, c, mode='full') / c.sum()
    ydc, remainder = scipy.signal.deconvolve(yc, c)
    ydc *= c.sum()
    
    fig, ax = plt.subplots(nrows=2, ncols=2, figsize=(4, 4))
    ax[0][0].plot(x, y, label="original y", lw=3)
    ax[0][1].plot(x, c, label="c", lw=3)
    ax[1][0].plot(x[0:2000], yc[0:2000], label="yc", lw=3)
    ax[1][1].plot(x, ydc, label="recovered y", lw=3)
    
    plt.show()
    
    0 讨论(0)
  • 2020-12-03 00:08

    After some trial and error I found out how to interprete the results of scipy.signal.deconvolve() and I post my findings as an answer.

    Let's start with a working example code

    import numpy as np
    import scipy.signal
    import matplotlib.pyplot as plt
    
    # let the signal be box-like
    signal = np.repeat([0., 1., 0.], 100)
    # and use a gaussian filter
    # the filter should be shorter than the signal
    # the filter should be such that it's much bigger then zero everywhere
    gauss = np.exp(-( (np.linspace(0,50)-25.)/float(12))**2 )
    print gauss.min()  # = 0.013 >> 0
    
    # calculate the convolution (np.convolve and scipy.signal.convolve identical)
    # the keywordargument mode="same" ensures that the convolution spans the same
    #   shape as the input array.
    #filtered = scipy.signal.convolve(signal, gauss, mode='same') 
    filtered = np.convolve(signal, gauss, mode='same') 
    
    deconv,  _ = scipy.signal.deconvolve( filtered, gauss )
    #the deconvolution has n = len(signal) - len(gauss) + 1 points
    n = len(signal)-len(gauss)+1
    # so we need to expand it by 
    s = (len(signal)-n)/2
    #on both sides.
    deconv_res = np.zeros(len(signal))
    deconv_res[s:len(signal)-s-1] = deconv
    deconv = deconv_res
    # now deconv contains the deconvolution 
    # expanded to the original shape (filled with zeros) 
    
    
    #### Plot #### 
    fig , ax = plt.subplots(nrows=4, figsize=(6,7))
    
    ax[0].plot(signal,            color="#907700", label="original",     lw=3 ) 
    ax[1].plot(gauss,          color="#68934e", label="gauss filter", lw=3 )
    # we need to divide by the sum of the filter window to get the convolution normalized to 1
    ax[2].plot(filtered/np.sum(gauss), color="#325cab", label="convoluted" ,  lw=3 )
    ax[3].plot(deconv,         color="#ab4232", label="deconvoluted", lw=3 ) 
    
    for i in range(len(ax)):
        ax[i].set_xlim([0, len(signal)])
        ax[i].set_ylim([-0.07, 1.2])
        ax[i].legend(loc=1, fontsize=11)
        if i != len(ax)-1 :
            ax[i].set_xticklabels([])
    
    plt.savefig(__file__ + ".png")
    plt.show()    
    

    This code produces the following image, showing exactly what we want (Deconvolve(Convolve(signal,gauss) , gauss) == signal)

    Some important findings are:

    • The filter should be shorter than the signal
    • The filter should be much bigger than zero everywhere (here > 0.013 is good enough)
    • Using the keyword argument mode = 'same' to the convolution ensures that it lives on the same array shape as the signal.
    • The deconvolution has n = len(signal) - len(gauss) + 1 points. So in order to let it also reside on the same original array shape we need to expand it by s = (len(signal)-n)/2 on both sides.

    Of course, further findings, comments and suggestion to this question are still welcome.

    0 讨论(0)
提交回复
热议问题