Doubly circulant matrices
# How the Inverse of a Doubly Circulant Matrix is Equivlant to a 2D Deconvolution?
## Import some packages
import matplotlib.pylab as plt
import numpy as np
from numpy.fft import rfft, irfft, rfftfreq, rfft2, irfft2, fft2, ifft2
import astropy.io.fits as pyfits
import scipy.linalg
## Define some functions
# A function to calculate the elements of a covariance matrix
def cov(df, dt, nch, ntime):
if dt>ntime/2:
dt-=ntime
if df>nch/2:
df-=nch
if dt<=-ntime/2:
dt+=ntime
if df<=-nch/2:
df+=nch
if dt==0:
dt=1
if df==0:
df=1
return (abs(dt)/8)**-1*(abs(df)/4)**-1
# fill the content of a covariance matrix
def fill_cov_matrix(nch=16, ntime=32):
result=np.zeros([nch*ntime, nch*ntime])
for t1 in range(ntime):
for f1 in range(nch):
for t2 in range(ntime):
for f2 in range(nch):
i=f1*ntime+t1
j=f2*ntime+t2
result[i,j]=cov(f2-f1, t2-t1, nch, ntime)
return result
# generating the equivlant deconvolution kernel
def fill_cov_kernel(nch=16, ntime=32):
result=np.zeros([ntime, nch])
for t1 in range(ntime):
for f1 in range(nch):
result[t1, f1]=cov(f1, t1, nch, ntime)
return result
# flattern a 2-D array to 1-D
def flattern(m):
return m.reshape(m.size, order='F')
# unflattern a 1-D array to 2-D
def unflattern(m, nch):
ntime=m.size//nch
return m.reshape((ntime, nch), order='F')
## Generating the doubly circulant matrix and the equivlant deconvolution kernel
ntime=32
nch=16
m=fill_cov_matrix(nch, ntime)
k=fill_cov_kernel(nch, ntime)
plt.imshow(m)
plt.colorbar()
<matplotlib.colorbar.Colorbar at 0x7f7afb8aecd0>
plt.figure(figsize=(5,7))
plt.imshow(k)
plt.colorbar()
<matplotlib.colorbar.Colorbar at 0x7f7afb7b1e10>
## Generate a random matrix, to which the doubly circulant matrix will be multiplied.
data2d=np.random.normal(size=(ntime, nch))
plt.imshow(data2d)
<matplotlib.image.AxesImage at 0x7f7afb875e90>
# Directly multiply the doubly circulant matrix
data1d=flattern(data2d)
convolved1d=unflattern(scipy.linalg.solve(m, data1d), nch)
plt.imshow(convolved1d)
<matplotlib.image.AxesImage at 0x7f7af5e82d50>
## Use a FFT2 to perform the same operation
convolved2d=irfft2(rfft2(data2d)/rfft2(k))
plt.imshow(convolved2d)
<matplotlib.image.AxesImage at 0x7f7af5e62f50>
## Calculate the difference
plt.imshow(convolved1d-convolved2d)
plt.colorbar()
<matplotlib.colorbar.Colorbar at 0x7f7af5d7fd50>