コード例 #1
0
    def batchreconstructcompact(self, img):
        nim = img.shape[0]
        r = np.mod(nim, 6)
        if r > 0:  # pad with empty frames so total number of frames is divisible by 6
            img = np.concatenate((img, np.zeros((6 - r, self.N, self.N), np.single)))
            nim = nim + 6 - r
        nim3 = nim // 3
        imf = fft.rfft2(img) * self._prefilter[:, 0:self.N // 2 + 1]
        img2 = np.zeros([nim, 2 * self.N, 2 * self.N], dtype=np.single)
        for i in range(0, nim, 3):
            self._carray1[:, 0:self.N // 2, 0:self.N // 2 + 1] = imf[i:i + 3, 0:self.N // 2, 0:self.N // 2 + 1]
            self._carray1[:, 3 * self.N // 2:2 * self.N, 0:self.N // 2 + 1] = imf[i:i + 3, self.N // 2:self.N,
                                                                              0:self.N // 2 + 1]
            img2[i:i + 3, :, :] = fft.irfft2(self._carray1) * self._reconfactor
        res = np.zeros((nim3, 2 * self.N, 2 * self.N), dtype=np.single)

        imgf = fft.rfft(img2[:, :self.N, :self.N], nim, 0)[:nim3 // 2 + 1, :, :]
        res[:, :self.N, :self.N] = fft.irfft(imgf, nim3, 0)
        imgf = fft.rfft(img2[:, :self.N, self.N:2 * self.N], nim, 0)[:nim3 // 2 + 1, :, :]
        res[:, :self.N, self.N:2 * self.N] = fft.irfft(imgf, nim3, 0)
        imgf = fft.rfft(img2[:, self.N:2 * self.N, :self.N], nim, 0)[:nim3 // 2 + 1, :, :]
        res[:, self.N:2 * self.N, :self.N] = fft.irfft(imgf, nim3, 0)
        imgf = fft.rfft(img2[:, self.N:2 * self.N, self.N:2 * self.N], nim, 0)[:nim3 // 2 + 1, :, :]
        res[:, self.N:2 * self.N, self.N:2 * self.N] = fft.irfft(imgf, nim3, 0)

        res = fft.irfft2(fft.rfft2(res) * self._postfilter[:, :self.N + 1])
        return res
コード例 #2
0
 def rfft2(self, field):
     """Convenience wrapper for real-valued 2D FFT."""
     if PYFFTW_AVAILABLE:
         num_thread = min(field.shape[0], self.max_num_thread)
         return fft.rfft2(field, norm="ortho", threads=num_thread)
     else:
         return fft.rfft2(field, norm="ortho")
コード例 #3
0
ファイル: deblur.py プロジェクト: PythonNut/photo-deblur
def main(blur_name, kernel_data_name, deconvolved_name):
    with h5py.File(kernel_data_name, 'r') as h5f:
        kernel = h5f['dataset_1'][:]

    # cut the low frequency components out, since we know they don't
    # contain any useful information. This has the side-effect of
    # significantly speeding up the deconvolution.
    # x, y, _ = kernel.shape
    # shift = np.fft.fftshift(kernel)
    # shift_clip = shift[floor(x/2 - 20):ceil(x/2 + 20), floor(y/2-20):ceil(y/2 + 20), :]
    # kernel_small = np.fft.fftshift(shift_clip)

    blur = plt.imread(blur_name)[:, :, :3]

    print("Kernel has size: " + str(kernel.shape[:2]))
    print("Blurred image has size: " + str(blur.shape[:2]))
    kernel, blur = resize_to_fit(kernel, blur)
    print("Cropped to size: " + str(blur.shape[:2]))

    # deconvolved = restoration.richardson_lucy(blur, kernel_small)

    blur_f = fft.rfft2(blur, axes=(0, 1), threads=16)
    kernel_f = fft.rfft2(kernel, axes=(0, 1), threads=16)

    deconvolved_f = blur_f / kernel_f
    deconvolved = np.nan_to_num(fft.irfft2(deconvolved_f, axes=(0, 1), threads=16))

    imwrite(deconvolved_name, deconvolved)
コード例 #4
0
 def reconstructframe_rfftw(self, img, i):
     diff = img - self._imgstore[i, :, :]
     imf = fft.rfft2(diff) * self._prefilter[:, 0:self.N // 2 + 1]
     self._carray1[0, 0:self.N // 2, 0:self.N // 2 + 1] = imf[0:self.N // 2, 0:self.N // 2 + 1]
     self._carray1[0, 3 * self.N // 2:2 * self.N, 0:self.N // 2 + 1] = imf[self.N // 2:self.N, 0:self.N // 2 + 1]
     img2 = fft.irfft2(self._carray1[0, :, :]) * self._reconfactor[i, :, :]
     self._imgstore[i, :, :] = img
     self._bigimgstore = self._bigimgstore + fft.irfft2(fft.rfft2(img2) * self._postfilter[:, 0:self.N + 1])
     return self._bigimgstore
コード例 #5
0
 def reconstruct_rfftw(self, img):
     imf = fft.rfft2(img) * self._prefilter[:, 0:self.N // 2 + 1]
     self._carray1[:, 0:self.N // 2,
                   0:self.N // 2 + 1] = imf[:, 0:self.N // 2,
                                            0:self.N // 2 + 1]
     self._carray1[:, 3 * self.N // 2:2 * self.N,
                   0:self.N // 2 + 1] = imf[:, self.N // 2:self.N,
                                            0:self.N // 2 + 1]
     img2 = np.sum(fft.irfft2(self._carray1) * self._reconfactor, 0)
     return fft.irfft2(fft.rfft2(img2) * self._postfilter[:, 0:self.N + 1])
コード例 #6
0
def main(blur_name, orig_name, data_name, kernel_name):
    orig = plt.imread(orig_name)[:, :, :3]
    blur = plt.imread(blur_name)[:, :, :3]

    # blur = kernel * orig → kernel = blur/orig
    # kernel = restoration.richardson_lucy(blur, orig)

    orig_f = fft.rfft2(orig, axes=(0, 1), threads=16)
    blur_f = fft.rfft2(blur, axes=(0, 1), threads=16)

    kernel_f = blur_f / orig_f
    kernel = np.nan_to_num(fft.irfft2(kernel_f, axes=(0, 1), threads=16))

    with h5py.File(data_name, 'w') as h5f:
        h5f.create_dataset('dataset_1', data=kernel)

    imwrite(kernel_name, np.fft.fftshift(kernel) / kernel.max())
コード例 #7
0
    def batchreconstruct(self, img, n_output_frames=None):
        nim = img.shape[0]
        r = np.mod(nim, 14)
        if r > 0:  # pad with empty frames so total number of frames is divisible by 14
            img = np.concatenate((img, np.zeros((14 - r, self.N, self.N), np.single)))
            nim = nim + 14 - r
        imf = fft.rfft2(img) * self._prefilter[:, 0:self.N // 2 + 1]
        img2 = np.zeros([nim, 2 * self.N, 2 * self.N], dtype=np.single)
        for i in range(0, nim, 7):
            self._carray1[:, 0:self.N // 2, 0:self.N // 2 + 1] = imf[i:i + 7, 0:self.N // 2, 0:self.N // 2 + 1]
            self._carray1[:, 3 * self.N // 2:2 * self.N, 0:self.N // 2 + 1] = imf[i:i + 7, self.N // 2:self.N,
                                                                              0:self.N // 2 + 1]
            img2[i:i + 7, :, :] = fft.irfft2(self._carray1) * self._reconfactor

        nim7 = nim // 7
        if n_output_frames is None:
            n_output_frames = nim7

        img3 = fft.irfft(fft.rfft(img2, nim, 0)[0:nim7 // 2 + 1, :, :], n_output_frames, 0)
        res = fft.irfft2(fft.rfft2(img3) * self._postfilter[:, :self.N + 1])
        return res
コード例 #8
0
ファイル: tiehom2020.py プロジェクト: ElettraSciComp/STP-Core
def tiehom2020(im, plan, nr_threads=2):
	"""Process a tomographic projection image with the Generalized TIE-HOM (Paganin et al 2020) 
    phase retrieval algorithm.

	Parameters
	----------
	im : array_like
		Flat corrected image data as numpy array.

	plan : structure
		Structure with pre-computed data (see tiehom_plan function).

	nr_threads : int 
		Number of threads to be used in the computation of FFT by PyFFTW (default = 2).
		
	"""
	# Extract plan values:
	dim0_o = plan['dim0']
	dim1_o = plan['dim1']
	n_pad0 = plan['npad0']
	n_pad1 = plan['npad1']
	marg0 = (n_pad0 - dim0_o) / 2
	marg1 = (n_pad1 - dim1_o) / 2
	den = plan['den']
	mu = plan['mu']

	# Pad image (if required):	
	im = padImage(im, n_pad0, n_pad1) 

	# (Un)comment the following two lines to use PyFFTW:
	n_byte_align(im, simd_alignment) 
	im = rfft2(im, threads=nr_threads)			

	# (Un)comment the following line to use NumPy:
	#im = rfft2(im)

	# Apply Paganin's (pre-computed) formula:
	im = im / den
		
	# (Un)comment the following two lines to use PyFFTW:
	n_byte_align(im, simd_alignment)
	im = irfft2(im, threads=nr_threads)
		
	# (Un)comment the following line to use NumPy:
	#im = irfft2(im)
				
	im = im.astype(float32)		
	im = -1 / mu * nplog(im)    		

	# Return cropped output:
	return im[marg0:dim0_o + marg0, marg1:dim1_o + marg1] 
コード例 #9
0
ファイル: tiehom.py プロジェクト: ElettraSciComp/STP-Core
def tiehom(im, plan, nr_threads=2):
	"""Process a tomographic projection image with the TIE-HOM (Paganin's) phase retrieval algorithm.

	Parameters
	----------
	im : array_like
		Flat corrected image data as numpy array.

	plan : structure
		Structure with pre-computed data (see tiehom_plan function).

	nr_threads : int 
		Number of threads to be used in the computation of FFT by PyFFTW (default = 2).
		
	"""
	# Extract plan values:
	dim0_o = plan['dim0']
	dim1_o = plan['dim1']
	n_pad0 = plan['npad0']
	n_pad1 = plan['npad1']
	marg0 = (n_pad0 - dim0_o) / 2
	marg1 = (n_pad1 - dim1_o) / 2
	den = plan['den']
	mu = plan['mu']

	# Pad image (if required):	
	im = padImage(im, n_pad0, n_pad1) 

	# (Un)comment the following two lines to use PyFFTW:
	n_byte_align(im, simd_alignment) 
	im = rfft2(im, threads=nr_threads)			

	# (Un)comment the following line to use NumPy:
	#im = rfft2(im)

	# Apply Paganin's (pre-computed) formula:
	im = im / den
		
	# (Un)comment the following two lines to use PyFFTW:
	n_byte_align(im, simd_alignment)
	im = irfft2(im, threads=nr_threads)
		
	# (Un)comment the following line to use NumPy:
	#im = irfft2(im)
				
	im = im.astype(float32)		
	im = -1 / mu * nplog(im)    		

	# Return cropped output:
	return im[marg0:dim0_o + marg0, marg1:dim1_o + marg1] 
コード例 #10
0
def _update_stationary(image, dm, dn, B, cov):
    """Accumulate the stationary image statistics"""
    M,N,K = image.shape
    If = fft.rfft2(image.transpose(2,0,1), (M+B,N+B))
    Ic = If.conj()
    for k1 in range(K):
        for k2 in range(k1,K):

            #  cross correlate
            corr = fft.irfft2(Ic[k1]*If[k2], (M+B,N+B))
            # accumulate
            cov[dm,dn,k1,k2] += corr[dm,dn]
            if k1 != k2:
                cov[-dm,-dn,k2,k1] += corr[dm,dn]
コード例 #11
0
ファイル: sort.py プロジェクト: wwangat/pyem
def particle_xcorr(ptcl, refmap_ft):
    r = util.euler2rot(*np.deg2rad(ptcl[star.Relion.ANGLES]))
    proj = vop.interpolate_slice_numba(refmap_ft, r)
    c = ctf.eval_ctf(s / apix,
                     a,
                     def1[i],
                     def2[i],
                     angast[i],
                     phase[i],
                     kv[i],
                     ac[i],
                     cs[i],
                     bf=0,
                     lp=2 * apix)
    pshift = np.exp(-2 * np.pi * 1j * (-xshift[i] * sx + -yshift * sy))
    proj_ctf = proj * pshift * c

    with mrc.ZSliceReader(ptcl[star.Relion.IMAGE_NAME]) as f:
        exp_image_fft = rfft2(fftshift(f.read(i)))

    xcor_fft = exp_image_fft * proj_ctf
    xcor = fftshift(irfft2(xcor_fft))
    return xcor
コード例 #12
0
ファイル: clustering_2d.py プロジェクト: Chiil/smallprograms
def calc_rhs(q):
    q_tend = fft.rfft2(c0*np.tanh(fft.irfft2(q))) \
           - c1*q \
           - nu * (kx[np.newaxis,:]**2 + ky[:,np.newaxis]**2) * q

    return q_tend
コード例 #13
0
ファイル: clustering_2d.py プロジェクト: Chiil/smallprograms
    a = fft.irfft2(afft)
    
    # normalize the variance to 1
    a *= a_std/np.std(a)
    return a

#h = generate_random_field(1.) + h0
q = generate_random_field(1.)

nt = 24*1000
dt = 6*3600.
t = 0.
n_out = 16

# Set all variables in Fourier space.
q = fft.rfft2(q)

def pad(a):
    a_pad = np.zeros((3*ny//2, 3*nx//4+1), dtype=np.complex)
    a_pad[:ny//2,:nx//2+1] = a[:ny//2,:]
    a_pad[ny:3*ny//2,:nx//2+1] = a[ny//2:,:]
    return (9/4)*a_pad

def unpad(a_pad):
    a = np.zeros((ny, nx//2+1), dtype=complex)
    a[:ny//2,:] = a_pad[:ny//2,:nx//2+1]
    a[ny//2:,:] = a_pad[ny:3*ny//2,:nx//2+1]
    return (4/9)*a

def calc_prod(a, b):
    a_pad = pad(a)
コード例 #14
0
def calc_rhs(q):
    q_tend = fft.rfft2(nd1*np.tanh(fft.irfft2(q))) \
           - nd2*q \
           - (kx[np.newaxis,:]**2 + ky[:,np.newaxis]**2) * q

    return q_tend
コード例 #15
0
def calc_prod(a, b):
    return fft.rfft2( fft.irfft2(a) * fft.irfft2(b) )
コード例 #16
0
def homomorphic(im, args):
    """Process the input image with an homomorphic filtering.

	Parameters
	----------
	im : array_like
		Image data as numpy array.	

	d0 : float
		Cutoff in the range [0.01, 0.99] of the high pass Gaussian filter. 
        Higher values means more high pass effect. [Suggested for default: 0.80].

    alpha : float
		Offset to preserve the zero frequency where. Higher values means less 
        high pass effect. [Suggested for default: 0.2]

	(Parameters d0 and alpha have to passed as a string separated by ;)
		   
	Example (using tiffile.py)
	--------------------------
	>>> im = imread('im_orig.tif')
	>>> im = homomorphic(im, '0.5;0.2')    
	>>> imsave('im_flt.tif', im) 
	

	References
	----------
  

	"""
    # Get args:
    param1, param2 = args.split(";")
    d0 = (1.0 - float(param1))  # Simpler for user
    alpha = float(param2)

    # Internal parameters for Gaussian low-pass filtering:
    d0 = d0 * (im.shape[1] / 2.0)

    # Take the log:
    im = nplog(1 + im)

    # Compute FFT:
    n_byte_align(im, simd_alignment)
    im = rfft2(im, threads=2)

    # Prepare the frequency coordinates:
    u = arange(0, im.shape[0], dtype=float32)
    v = arange(0, im.shape[1], dtype=float32)

    # Compute the indices for meshgrid:
    u[(u > im.shape[0] / 2.0)] = u[(u > im.shape[0] / 2.0)] - im.shape[0]
    v[(v > im.shape[1] / 2.0)] = v[(v > im.shape[1] / 2.0)] - im.shape[1]

    # Compute the meshgrid arrays:
    V, U = meshgrid(v, u)

    # Compute the distances D(U, V):
    D = sqrt(U**2 + V**2)

    # Prepare Guassian filter:
    H = npexp(-(D**2) / (2 * (d0**2)))
    H = (1 - H) + alpha

    # Do the filtering:
    im = H * im

    # Compute inverse FFT of the filtered data:
    n_byte_align(im, simd_alignment)
    #im = real(irfft2(im, threads=2))
    im = irfft2(im, threads=2)

    # Take the exp:
    im = npexp(im) - 1

    # Return image according to input type:
    return im.astype(float32)
コード例 #17
0
    
    a = fft.irfft2(afft)
    
    # normalize the variance to 1
    a *= a_std/np.std(a)
    return a

#h = generate_random_field(1.) + h0
q = generate_random_field(1.)

nt = 172800
dt = 100.
t = 0.

# Set all variables in Fourier space.
u = fft.rfft2(u)
v = fft.rfft2(v)
h = fft.rfft2(h)
q = fft.rfft2(q)

def pad(a):
    a_pad = np.zeros((3*ny//2, 3*nx//4+1), dtype=np.complex)
    a_pad[:ny//2,:nx//2+1] = a[:ny//2,:]
    a_pad[ny:3*ny//2,:nx//2+1] = a[ny//2:,:]
    return (9/4)*a_pad

def unpad(a_pad):
    a = np.zeros((ny, nx//2+1), dtype=complex)
    a[:ny//2,:] = a_pad[:ny//2,:nx//2+1]
    a[ny//2:,:] = a_pad[ny:3*ny//2,:nx//2+1]
    return (4/9)*a
コード例 #18
0
def integrate_dpc(xshift,
                  yshift,
                  padf=4,
                  lP=0.5,
                  hP=100,
                  stepsize=0.2,
                  iter_count=100):
    """
    Integrate DPC shifts using Fourier transforms and
    preventing edge effects

    Parameters
    ----------
    xshift:     ndarray
                Beam shift in the X dimension
    yshift:     ndarray
                Beam shift in the X dimensions
    padf:       int, optional
                padding factor for accurate FFT,
                default is 4
    lP:         float, optional
                low pass filter, default is 0.5
    hP:         float, optional
                high pass filter, default is 100
    stepsize:   float, optional
                fraction of phase differnce to update every
                iteration. Default is 0.5. This is a dynamic
                factor, and is reduced if the error starts
                increasing
    iter_count: int, optional
                Number of iterations to run. Default is 100

    Returns
    -------
    phase_final: ndarray
                 Phase of the matrix that leads to the displacement

    Notes
    -----
    This is based on two ideas - iterative complex plane
    integration and antisymmetric mirror integration. First
    two antisymmetric matrices are generated for each of the
    x shift and y shifts. Then they are integrated in Fourier
    space as per the idea of complex integration. Finally, a
    sub-matrix is taken out from the antisymmetric integrand
    matrix to give the dpc integrand

    References
    ----------
    .. [1] Ishizuka, Akimitsu, Masaaki Oka, Takehito Seki, Naoya Shibata,
        and Kazuo Ishizuka. "Boundary-artifact-free determination of
        potential distribution from differential phase contrast signals."
        Microscopy 66, no. 6 (2017): 397-405.

    :Authors:
    Debangshu Mukherjee <*****@*****.**>
    """
    imshape = np.asarray(xshift.shape)
    padshape = (imshape * padf).astype(int)
    qx = np.fft.fftfreq(padshape[0])
    qy = np.fft.rfftfreq(padshape[1])
    qr2 = qx[:, None]**2 + qy[None, :]**2

    denominator = qr2 + hP + ((qr2**2) * lP)
    _ = np.seterr(divide="ignore")
    denominator = 1.0 / denominator
    denominator[0, 0] = 0
    _ = np.seterr(divide="warn")
    f = 1j * 0.25 * stepsize
    qxOperator = f * qx[:, None] * denominator
    qyOperator = f * qy[None, :] * denominator

    padded_phase = np.zeros(padshape)
    update = np.zeros_like(padded_phase)
    dx = np.zeros_like(padded_phase)
    dy = np.zeros_like(padded_phase)
    error = np.zeros(iter_count)
    mask = np.zeros_like(padded_phase, dtype=bool)
    mask[int(0.5 * (padshape[0] - imshape[0])):int(0.5 *
                                                   (padshape[0] + imshape[0])),
         int(0.5 * (padshape[1] - imshape[1])):int(0.5 *
                                                   (padshape[1] +
                                                    imshape[1])), ] = True
    maskInv = mask == False
    for ii in range(iter_count):
        dx[mask] -= xshift.ravel()
        dy[mask] -= yshift.ravel()
        dx[maskInv] = 0
        dy[maskInv] = 0
        update = pfft.irfft2(
            pfft.rfft2(dx) * qxOperator + pfft.rfft2(dy) * qyOperator)
        padded_phase += scnd.gaussian_filter((stepsize * update), 1)
        dx = (np.roll(padded_phase, (-1, 0), axis=(0, 1)) -
              np.roll(padded_phase, (1, 0), axis=(0, 1))) / 2.0
        dy = (np.roll(padded_phase, (0, -1), axis=(0, 1)) -
              np.roll(padded_phase, (0, 1), axis=(0, 1))) / 2.0
        xDiff = dx[mask] - xshift.ravel()
        yDiff = dy[mask] - yshift.ravel()
        error[ii] = np.sqrt(
            np.mean((xDiff - np.mean(xDiff))**2 + (yDiff - np.mean(yDiff))**2))
        if ii > 0:
            if error[ii] > error[ii - 1]:
                stepsize /= 2
    phase_final = np.reshape(padded_phase[mask], imshape)
    return phase_final
コード例 #19
0
def homomorphic(im, args):
	"""Process the input image with an homomorphic filtering.

	Parameters
	----------
	im : array_like
		Image data as numpy array.	

	d0 : float
		Cutoff in the range [0.01, 0.99] of the high pass Gaussian filter. 
        Higher values means more high pass effect. [Suggested for default: 0.80].

    alpha : float
		Offset to preserve the zero frequency where. Higher values means less 
        high pass effect. [Suggested for default: 0.2]

	(Parameters d0 and alpha have to passed as a string separated by ;)
		   
	Example (using tiffile.py)
	--------------------------
	>>> im = imread('im_orig.tif')
	>>> im = homomorphic(im, '0.5;0.2')    
	>>> imsave('im_flt.tif', im) 
	

	References
	----------
  

	"""    
	# Get args:
	param1, param2 = args.split(";")       	 
	d0 = (1.0 - float(param1))  # Simpler for user
	alpha = float(param2) 
	
	# Internal parameters for Gaussian low-pass filtering:
	d0 = d0 * (im.shape[1] / 2.0)	

	# Take the log:
	im = nplog(1 + im)

	# Compute FFT:
	n_byte_align(im, simd_alignment) 
	im = rfft2(im, threads=2)

	# Prepare the frequency coordinates:
	u = arange(0, im.shape[0], dtype=float32)
	v = arange(0, im.shape[1], dtype=float32)

	# Compute the indices for meshgrid:
	u[(u > im.shape[0] / 2.0)] = u[(u > im.shape[0] / 2.0)] - im.shape[0]    
	v[(v > im.shape[1] / 2.0)] = v[(v > im.shape[1] / 2.0)] - im.shape[1]

	# Compute the meshgrid arrays:
	V, U = meshgrid(v, u)

	# Compute the distances D(U, V):
	D = sqrt(U ** 2 + V ** 2)

	# Prepare Guassian filter:
	H = npexp(-(D ** 2) / (2 * (d0 ** 2)))
	H = (1 - H) + alpha
	
	# Do the filtering:
	im = H * im   

	# Compute inverse FFT of the filtered data:
	n_byte_align(im, simd_alignment)
	#im = real(irfft2(im, threads=2))
	im = irfft2(im, threads=2)

	# Take the exp:
	im = npexp(im) - 1

	# Return image according to input type:
	return im.astype(float32)
コード例 #20
0
def calc_prod(a, b):
    a_pad = pad(a)
    b_pad = pad(b)

    ab_pad = fft.rfft2( fft.irfft2(a_pad) * fft.irfft2(b_pad) )
    return unpad(ab_pad)
コード例 #21
0
ファイル: raven.py プロジェクト: ElettraSciComp/STP-Core
def raven(im, args):
	"""Process a sinogram image with the Raven de-striping algorithm.
	
	Parameters
	----------
	im : array_like
		Image data as numpy array.

	n : int
		Size of the window (minimum n = 3) around the zero frequency where 
		filtering is actually applied (v0 parameter in Raven's article). Higher 
		values	means more smoothing effect. [Suggested for default: 3]

	d0 : float
		Cutoff in the range [0.01, 0.99] of the low pass filter (a Gaussian filter 
		is used instead of the originally proposed Butterworth filter in order to 
		have only one tuning parameter). Higher values means more smoothing effect. 
		[Suggested for default: 0.5].

	(Parameters n and d0 have to passed as a string separated by ;)
		   
	Example (using tiffile.py)
	--------------------------
	>>> im = imread('sino_orig.tif')
	>>> im = raven(im, '3;0.50')    
	>>> imsave('sino_flt.tif', im) 

	References
	----------
	C. Raven, Numerical removal of ring artifacts in microtomography,
	Review of Scientific Instruments 69(8):2978-2980, 1998.

	"""    
	# Disable a warning:
	simplefilter("ignore", ComplexWarning)
	
	# Get args:
	param1, param2 = args.split(";")    
	n = int(param1) 
	d0 = (1.0 - float(param2))  # Simpler for user
	
	# Internal parameters for Gaussian low-pass filtering:
	d0 = d0 * (im.shape[1] / 2.0)

	# Pad image:
	marg = im.shape
	im = pad(im, pad_width=((im.shape[0] / 2, im.shape[0] / 2), (0,0)), mode='reflect') # or 'constant' for zero padding
	im = pad(im, pad_width=((0,0) ,(im.shape[1] / 2, im.shape[1] / 2)), mode='edge')    # or 'constant' for zero padding

	# Windowing:
	im = _windowing_lr(im, marg[1])
	im = _windowing_lr(im.T, marg[0]).T	

	# Compute FFT:
	n_byte_align(im, simd_alignment) 
	im = rfft2(im, threads=2)

	# Prepare the frequency coordinates:
	u = arange(0, im.shape[0], dtype=float32)
	v = arange(0, im.shape[1], dtype=float32)

	# Compute the indices for meshgrid:
	u[(u > im.shape[0] / 2.0)] = u[(u > im.shape[0] / 2.0)] - im.shape[0]    
	v[(v > im.shape[1] / 2.0)] = v[(v > im.shape[1] / 2.0)] - im.shape[1]

	# Compute the meshgrid arrays:
	V, U = meshgrid(v, u)

	# Compute the distances D(U, V):
	D = sqrt(U ** 2 + V ** 2)

	# Prepare Guassian filter limited to a window around zero-frequency:
	H = exp(-(D ** 2) / (2 * (d0 ** 2)))
	if (n % 2 == 1):
		H[n / 2:-(n / 2),:] = 1
	else:
		H[n / 2:-(n / 2 - 1),:] = 1

	# Do the filtering:
	im = H * im   

	# Compute inverse FFT of the filtered data:
	n_byte_align(im, simd_alignment)
	#im = real(irfft2(im, threads=2))
	im = irfft2(im, threads=2)

	# Crop image:
	im = im[im.shape[0] / 4:(im.shape[0] / 4 + marg[0]), im.shape[1] / 4:(im.shape[1] / 4 + marg[1])]

	# Return image:
	return im.astype(float32)