[SciPy-User] deconvolution of 1-D signals
David Baddeley
david_baddeley at yahoo.com.au
Mon Aug 1 03:03:18 EDT 2011
Hi Ralf,
5-15 times smaller would probably be fine, although you might want to watch the
edges in the reconstruction - if they're at different dc levels you'll get edge
artifacts (within ~ 1 kernel width of the edges). I'd tend to avoid spline
filtering (or any form of noise reduction) before deconvolution, as this will
also transform the data in a way not explained by the model you're using to
deconvolve with.
Weiner filtering is a 2 liner ->
H = fft(kernel)
deconvolved = ifftshift(ifft(fft(signal)*np.conj(H)/(H*np.conj(H) + lambda**2)))
where lambda is your regularisation parameter, and white noise is assumed. There
are various methods for choosing lambda optimally, but most people tend to use
trial and error.
Iterative methods are typically ~1-2 orders of magnitude slower than a Weiner
filter, but with fast fft libraries and modern computers still quite reasonable
for modest data sizes (a 3D image stack of ~ 512x512x50 pixels will tend to be
done in a bit under a minute, can't really comment on 1D data, but unless your
signal is very long I'd expect it to be significantly quicker). Ffts scale with
O(nlogn) so will generally dramatically outperform things based on a simple
convolution or filtering approaches (O(n**2)) for large n. This might make an
iterative approach using ffts faster than something like scipy.signal.deconvolve
if your kernel is large.
cheers,
David
________________________________
From: Ralf Gommers <ralf.gommers at googlemail.com>
To: David Baddeley <david_baddeley at yahoo.com.au>; SciPy Users List
<scipy-user at scipy.org>
Sent: Mon, 1 August, 2011 6:03:10 PM
Subject: Re: [SciPy-User] deconvolution of 1-D signals
On Mon, Aug 1, 2011 at 2:51 AM, David Baddeley <david_baddeley at yahoo.com.au>
wrote:
Hi Ralf,
>
>
>I do a reasonable amount of (2 & 3D) deconvolution of microscopy images and the
>method I use depends quite a lot on the exact properties of the signal. You can
>usually get away with fft based convolutions even if your signal is not periodic
>as long as your kernel is significantly smaller than the signal extent.
The kernel is typically about 5 to 15 times smaller than the signal extent, so I
guess that may be problematic.
>
>As Joe mentioned, for a noisy signal convolving with the inverse or performing
>fourier domain division doesn't work as you end up amplifying high frequency
>noise components. You thus need some form of regularisation. The thresholding of
>fourier components that Joe suggests does this, but you might also want to
>explore more sophisticated options, the simplest of which is probably Wiener
>filtering (http://en.wikipedia.org/wiki/Wiener_deconvolution).
I'm aware of the problems with high frequency noise. This is why I tried the
spline fitting - I figured that on a spline the deconvolution would be okay
because the spline is very smooth. This should be fine for my data because the
noise is much higher-frequency than the underlying signal, and the SNR is high
to start with. But maybe there are better ways. I looked for a Python
implementation of Wiener deconvolution but couldn't find one so quickly. Is
there a package out there that has it?
>
>If you've got a signal which is constrained to be positive, it's often useful to
>introduce a positivity constraint on the deconvolution result which generally
>means you need an iterative algorithm. The choice of algorithm should also
>depend on the type of noise that is present in your signal - my image data is
>constrained to be +ve and typically has either Poisson or a mixture of Poisson
>and Gaussian noise and I use either the Richardson-Lucy or a weighted version of
>ICTM (Iterative Constrained Tikhonov-Miller) algorithm. I can provide more
>details of these if required.
>
By constrained to be positive I'm guessing you mean monotonic? Otherwise I could
just add a constant offset, but that's probably not what you mean. What's
typically the speed penalty for an iterative method?
Ralf
>
cheers,
>David
>
>
>
>
>
>
>
>
>
________________________________
From: Ralf Gommers <ralf.gommers at googlemail.com>
>To: SciPy Users List <scipy-user at scipy.org>
>Sent: Mon, 1 August, 2011 5:56:49 AM
>Subject: [SciPy-User] deconvolution of 1-D signals
>
>
>Hi,
>
>For a measured signal that is the convolution of a real signal with a response
>function, plus measurement noise on top, I want to recover the real signal.
>Since I know what the response function is and the noise is high-frequency
>compared to the real signal, a straightforward approach is to smooth the
>measured signal (or fit a spline to it), then remove the response function by
>deconvolution. See example code below.
>
>Can anyone point me towards code that does the deconvolution efficiently?
>Perhaps signal.deconvolve would do the trick, but I can't seem to make it work
>(except for directly on the output of np.convolve(y, window, mode='valid')).
>
>Thanks,
>Ralf
>
>
>import numpy as np
>from scipy import interpolate, signal
>import matplotlib.pyplot as plt
>
># Real signal
>x = np.linspace(0, 10, num=201)
>y = np.sin(x + np.pi/5)
>
># Noisy signal
>mode = 'valid'
>window_len = 11.
>window = np.ones(window_len) / window_len
>y_meas = np.convolve(y, window, mode=mode)
>y_meas += 0.2 * np.random.rand(y_meas.size) - 0.1
>if mode == 'full':
> xstep = x[1] - x[0]
> x_meas = np.concatenate([ \
> np.linspace(x[0] - window_len//2 * xstep, x[0] - xstep,
>num=window_len//2),
> x,
> np.linspace(x[-1] + xstep, x[-1] + window_len//2 * xstep,
>num=window_len//2)])
>elif mode == 'valid':
> x_meas = x[window_len//2:-window_len//2+1]
>elif mode == 'same':
> x_meas = x
>
># Approximating spline
>xs = np.linspace(0, 10, num=500)
>knots = np.array([1, 3, 5, 7, 9])
>tck = interpolate.splrep(x_meas, y_meas, s=0, k=3, t=knots, task=-1)
>ys = interpolate.splev(xs, tck, der=0)
>
># Find (low-frequency part of) original signal by deconvolution of smoothed
># measured signal and known window.
>y_deconv = signal.deconvolve(ys, window)[0] #FIXME
>
># Plot all signals
>fig = plt.figure()
>ax = fig.add_subplot(111)
>
>ax.plot(x, y, 'b-', label="Original signal")
>ax.plot(x_meas, y_meas, 'r-', label="Measured, noisy signal")
>ax.plot(xs, ys, 'g-', label="Approximating spline")
>ax.plot(xs[window.size//2-1:-window.size//2], y_deconv, 'k-',
> label="signal.deconvolve result")
>ax.set_ylim([-1.2, 2])
>ax.legend()
>
>plt.show()
>
>
>_______________________________________________
>SciPy-User mailing list
>SciPy-User at scipy.org
>http://mail.scipy.org/mailman/listinfo/scipy-user
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.scipy.org/pipermail/scipy-user/attachments/20110801/f81b43ee/attachment.html>
More information about the SciPy-User
mailing list