Can I use ListDeconvolve or any other functions to get the original kernel?
In this case, the following works just fine:
LeastSquares[
Transpose@Through[{RotateLeft, Identity, RotateRight}[data1]],
conv
]
{0.333333, 0.333333, 0.333333}
More general with kernel length 2 k + 1
:
a = RandomReal[{-1, 1}, 100];
k = 20;
ker = RandomReal[{-1, 1}, 2 k + 1];
b = ListConvolve[ker, a, k + 1];
ker1 = LeastSquares[
Transpose[RotateRight[a, #] & /@ Range[-k, k]],
b
];
Max[Abs[ker - ker1]]
2.27596*10^-15
This is a bit roundabout but one can treat this as a polynomial algebra problem. First pad both ends of data and convolution result with zeros so that the convolution emulates polynomial multiplication. Then do a division to get the kernel as a polynomial.
data1 = {0., 0., 1., 2., 1., 2., 1., 0., 0., 0.};
ker = {1/3, 1/3, 1/3};
conv = ListConvolve[ker, data1, 2];
Augment:
data2 = Join[{0.}, data1, {0.}];
conv2 = Join[{0., 0.}, conv, {0., 0.}];
Rewrite as explicit polynomials:
polyfactor = data2.x^Range[0, Length[data2] - 1];
polyprod = conv2.x^Range[0, Length[conv2] - 1];
Compute the kernel as coefficients of the polynomial quotient:
CoefficientList[Chop[PolynomialQuotient[polyprod, polyfactor, x]], x]
(* {0.333333333333, 0.333333333333, 0.333333333333} *)
If actual examples are large and efficiency is a concern, there are equivalent but faster ways to recover the kernel e.g. emulating the division using a Fourier transform.
To approximate ker
using ListDeconvolve
, use data1
as the kernel. Increasing MaxIterations
can improve the approximation.
data1 = {0., 0., 1., 2., 1., 2., 1., 0., 0., 0.};
ker = {1/3, 1/3, 1/3};
conv = ListConvolve[ker, data1, 2];
Column[ListDeconvolve[data1, conv, MaxIterations -> #,
Method -> "RichardsonLucy"][[5 ;; 7]] & /@ Range[10, 40, 10]]