FUNCTION xrt_fft_convolution, x, y, correlation=correlation, nopad=nopad ; ========================================================================= ;+ ; PROJECT: ; ; Solar-B / XRT ; ; NAME: ; ; XRT_FFT_CONVOLUTION ; ; CATEGORY: ; ; Math utils ; ; PURPOSE: ; ; Perform 1-dimensional convolution (optionally correlation) by using ; the Fast Fourier Transform (FFT) and appropriate padding to avoid ; edge effects. ; ; CALLING SEQUENCE: ; ; images_convolved = XRT_FFT_CONVOLUTION(x, y, nopad=nopad) ; ; images_correlated = XRT_FFT_CONVOLUTION(x, y, nopad=nopad, /correlation) ; ; INPUTS: ; ; X - [Mandatory] (float or double precision 1D array, [Nx]) ; One of the two images to be convolved (or correlated). ; ; Y - [Mandatory] (float or double precision 1D array, [Ny]) ; One of the two images to be convolved (or correlated). ; ; KEYWORDS: ; ; /NOPAD - [Optional input] (byte, integer, or long scalar) ; If this keyword is set, then no zero padding will be ; performed on the arrays for the FFT. ; ; /CORRELATION - [Optional input] (byte, integer, or long scalar) ; If this keyword is set, then the correlation of X and Y ; instead of their convolution will be calculated. ; ; OUTPUTS: ; ; Return - [Mandatory] (float or double precision 1D array) ; This will be the convolution of the inputs X and Y, unless ; the /CORRELATION keyword is set, in which case the correlation ; array of X and Y will be returned. ; ; COMMON BLOCKS: ; ; none ; ; NOTES: ; ; none ; ; CONTACT: ; ; Comments, feedback, and bug reports regarding this routine may be ; directed to this email address: ; boerner ~at~ lmsal.com ; ; MODIFICATION HISTORY: ; ;progver = 'v2009-Mar-11' ;--- (P.Grigis (SAO)) Written. ;progver = 'v2012-Jan-03' ;--- (M.Weber (SAO)) Added a return line to the ; nopad=1 conditional section. ;progver = 'v2012-Jan-13' ;--- (M. Cheung (LMSAL)) Corrected calls to pg_fft_2dim_convolution to aia_fft_2dim_convolution ; progver = 'v2017-Apr-14' ;--- (P. Jibben (SAO)) Copied the AIA routines to the XRT directory and changed name for ; XRT use. ; ;- ; ========================================================================= nx=n_elements(x) ny=n_elements(y) n=max([nx,ny]) IF keyword_set(nopad) THEN BEGIN ;; This IF-THEN block is for the case where **no** zero-padding is indicated. IF keyword_set(correlation) THEN BEGIN fftres=fft(fft(x,-1)*conj(fft(y,-1)),1)*n ENDIF $ ELSE BEGIN fftres=fft(fft(x,-1)*fft(y,-1),1)*n ENDELSE RETURN,(shift(fftres,n/2)) ENDIF $ ELSE BEGIN ;; This ELSE block is for the case where zero-padding is indicated. neff=2LL^(ceil(alog(1.5*n)/alog(2))) xpad=fltarr(neff) ypad=fltarr(neff) xpad[neff/2-nx/2]=x ypad[neff/2-ny/2]=y IF keyword_set(correlation) THEN BEGIN fftres=fft(fft(xpad,-1)*conj(fft(ypad,-1)),1)*neff ENDIF $ ELSE BEGIN fftres=fft(fft(xpad,-1)*fft(ypad,-1),1)*neff ENDELSE RETURN,(shift(fftres,neff/2))[neff/2-n/2:neff/2+n/2-1] ENDELSE END ; ========================================================================= ; ========================================================================= FUNCTION xrt_fft_2dim_convolution, x, y, correlation=correlation, $ nopad=nopad, xpad=xpad, ypad=ypad ; ========================================================================= ;+ ; PROJECT: ; ; Solar-B / XRT ; ; NAME: ; ; XRT_FFT_2DIM_CONVOLUTION ; ; CATEGORY: ; ; Math utils ; ; PURPOSE: ; ; Perform 2-dimensional convolution (optionally correlation) by using ; FFT and appropriate padding to avoid edge effects. ; ; CALLING SEQUENCE: ; ; images_convolved = XRT_FFT_2DIM_CONVOLUTION(x, y, nopad=nopad) ; ; images_correlated = XRT_FFT_2DIM_CONVOLUTION(x, y, nopad=nopad, /correlation) ; ; INPUTS: ; ; X - [Mandatory] (float or double precision 1D array, [Nx]) ; One of the two images to be convolved (or correlated). ; ; Y - [Mandatory] (float or double precision 1D array, [Ny]) ; One of the two images to be convolved (or correlated). ; ; KEYWORDS: ; ; KEYWORDS: ; ; /CORRELATION - [Optional input] (byte, integer, or long scalar) ; If this keyword is set, then the correlation of X and Y ; instead of their convolution will be calculated. ; ; /NOPAD - [Optional input] (byte, integer, or long scalar) ; If this keyword is set, then no zero padding will be ; performed on the arrays for the FFT. ; ; XPAD - [Optional output] (float or double 2D array) ; This is the padding array for input X. ; ; YPAD - [Optional output] (float or double 2D array) ; This is the padding array for input Y. ; ; ; OUTPUTS: ; ; Return - [Mandatory] (float or double precision 2D array) ; This will be the convolution of the inputs X and Y, unless ; the /CORRELATION keyword is set, in which case the correlation ; array of X and Y will be returned. ; ; COMMON BLOCKS: ; ; none ; ; NOTES: ; ; none ; ; CONTACT: ; ; Comments, feedback, and bug reports regarding this routine may be ; directed to this email address: ; boerner ~at~ lmsal.com ; ; MODIFICATION HISTORY: ; ;progver = 'v2009-Mar-11' ;--- (P.Grigis (SAO)) Written. ;progver = 'v2009-Sep-28' ;--- (P.Grigis (SAO)) Investigate padding to see if ; it's correct... ; progver = 'v2017-Apr-14' ;--- (P. Jibben (SAO)) Copied the AIA routines to the XRT directory and changed name for ; XRT use. ;- ; ========================================================================= ;; Find sizes of input arrays. sx=size(x) sy=size(y) nx1=sx[1] ny1=sx[2] nx2=sy[1] ny2=sy[2] n1=max([nx1,nx2]) n2=max([ny1,ny2]) IF keyword_set(nopad) THEN BEGIN ;; This IF-THEN block is for the case where **no** zero-padding is indicated. IF keyword_set(correlation) THEN BEGIN fftres=fft(fft(x,-1)*conj(fft(y,-1)),1)*n1*n2 ENDIF $ ELSE BEGIN fftres=fft(fft(x,-1)*fft(y,-1),1)*n1*n2 ENDELSE RETURN,(shift(fftres,n1/2,n2/2)) ENDIF $ ELSE BEGIN ;; This ELSE block is for the case where zero-padding is indicated. neff1=2LL^(ceil(alog(1.5*n1)/alog(2))) neff2=2LL^(ceil(alog(1.5*n2)/alog(2))) print,neff1,neff2 xpad=fltarr(neff1,neff2) ypad=fltarr(neff1,neff2) xpad[neff1/2-nx1/2,neff2/2-ny1/2]=x ypad[neff1/2-nx2/2,neff2/2-ny2/2]=y IF keyword_set(correlation) THEN BEGIN fftres=fft(fft(xpad,-1)*conj(fft(ypad,-1)),1)*neff1*neff2 ENDIF $ ELSE BEGIN fftres=fft(fft(xpad,-1)*fft(ypad,-1),1)*neff1*neff2 ENDELSE RETURN,(shift(fftres,neff1/2,neff2/2))[neff1/2-n1/2:neff1/2+n1/2-1,neff2/2-n2/2:neff2/2+n2/2-1] ENDELSE END ; ========================================================================= ; ========================================================================= FUNCTION xrt_deconvolve_richardsonlucy, image, psf, niter=niter, $ error=error, verbose=verbose, ihat=ihat, ohat=ohat, $ inputohat=inputohat ; ========================================================================= ;+ ; PROJECT: ; ; Solar-B / XRT ; ; NAME: ; ; XRT_DECONVOLVE_RICHARDSONLUCY ; ; CATEGORY: ; ; Image processing ; ; PURPOSE: ; ; Perform the Richardson-Lucy (RL) deconvolution of an image, given a ; Point Spread Function (PSF). (This routine should only be used in the ; case where the PSF is known and constant across the image. In cases ; where the PSF is not known, a different, blind deconvolution scheme ; should be used instead.) ; ; CALLING SEQUENCE: ; ; deconvolved_image = xrt_deconvolve_richardsonlucy(image, psf, niter=niter) ; ; INPUTS: ; ; IMAGE - [Mandatory] (double or float array, [Ncols,Nrows]) ; The image or spectrum to be deconvolved. ; ; PSF - [Mandatory] (double or float array, [Ncols,Nrows]) ; An array with the same number of dimensions as IMAGE, ; representing the Point Spread Function of the system that ; produced the image. PSF can have a different number of ; elements than IMAGE. ; ; KEYWORDS: ; ; ; NITER - [Optional input] (integer or long scalar) ; The number of iterations to be performed (default: 25). ; ; /VERBOSE - [Optional input] (Boolean scalar) ; If set, a record of the workings of the routine is ; printed to the screen. ; ; INPUTOHAT - [Optional input] (double or float complex array, [Ncols,Nrows]) ; Allows the user to input the OHAT array. This can be used, ; e.g., to restart the iteration if not enough runs were ; performed. ; ; ERROR - [Optional output] (integer scalar) ; The error state from the routine. ; The meaning of the values is described below: ; 0: successful completion ; 1: IMAGE or PSF have unallowed size ; (0 or more than 2 dimensions) ; 2: IMAGE or PSF have unallowed type ; (floating point or double required) ; ; IHAT - [Optional output] (double or float complex array, [Ncols,Nrows]) ; The final blurred object model. ; ; OHAT - [Optional output] (double or float complex array, [Ncols,Nrows]) ; The final object model. ; ; OUTPUTS: ; ; Return - [Mandatory] (double or float array, [Ncols,Nrows]) ; The deconvolved image, or -1 if an error has occurred. ; ; COMMON BLOCKS: ; ; none ; ; NOTES: ; ; 1) The RL algorithm performed here follows closely the algorithm ; explained in P. A. Jansson, Deconvolution of Images and Spectra, ; 2nd edition, 1997, Chapter 10. ; ; 2) This routine should only be used in the case where the Point Spread ; Function (PSF) is known and constant across the image. In cases ; where the PSF is not known, a different, blind deconvolution scheme ; should be used instead. ; ; 3) This program does **not** perform any adjustment of the ; PSF for image binning. The user is responsible for ; correctly preparing a binned PSF input if one is required ; for the image. ; ; CONTACT: ; ; Comments, feedback, and bug reports regarding this routine may be ; directed to this email address: ; boerner ~at~ lmsal.com ; ; MODIFICATION HISTORY: ; ;progver = 'v2009-Mar-11' ;--- (P.Grigis (SAO)) Written. ;progver = 'v2009-Apr-16' ;--- (P.Grigis (SAO)) Allowed complex ohat input/output. ;progver = 'v2009-Sep-28' ;--- (P.Grigis (SAO)) Note that padding seems to be ; broken - always use /nopad until fixed. ;progver = 'v2011-Jul-13' ;--- (P.Grigis (SAO)) Made /nopad the default. ; progver = 'v2017-Apr-14' ;--- (P. Jibben (SAO)) Copied the AIA routines to the XRT directory and changed name for ; XRT use. ; ;- ; ========================================================================= ;; Error status starts at "no error". error=0 ;; Padding functionality doesn't work, so turn off. nopad=1 ;; Set default number of iterations. niter=fcheck(niter,5) ;; Get image size and dimension. imsize=size(image) psfsize=size(psf) ;; Check for scalars or 3D arrays that may sneak in (we don't want those). IF imsize[0] EQ 0 OR imsize[0] GT 2 OR psfsize[0] EQ 0 OR psfsize[0] GT 2 OR imsize[0] NE psfsize[0] THEN BEGIN print,'Invalid image or PSF size. This function works only with 1- or 2-dimensional' print,'arrays, and both arguments must have the same dimension.' error=1 RETURN,-1 ENDIF ;; Check for numeric floating point types. The test below is true if either ;; IMAGE or PSF is not of type 4 or 5 (floating or double). IF ~(imsize[n_elements(imsize)-2] EQ 4 || imsize[n_elements(imsize)-2] EQ 5) || $ ~(psfsize[n_elements(psfsize)-2] EQ 4 || psfsize[n_elements(psfsize)-2] EQ 5) THEN BEGIN print,'Invalid image or PSF type. This function works only with floating point' print,'or double numeric arrays.' error=2 RETURN,-1 ENDIF twodim=imsize[0] EQ 2 ;; Print some general info on the screen. IF keyword_set(verbose) THEN BEGIN IF twodim THEN BEGIN print,' ' print,'Richardson-Lucy deconvolution (ver:'+progver+') of a '+strtrim(imsize[1],2)+'x'+strtrim(imsize[2],2)+' image' + $ ' and a '+strtrim(psfsize[1],2)+'x'+strtrim(psfsize[2],2)+ ' PSF.' print,' ' ENDIF $ ELSE BEGIN print,' ' print,'Richardson-Lucy deconvolution (ver:'+progver+') of a '+strtrim(n_elements(image),2)+ $ '-element spectrum with a '+strtrim(n_elements(psf),2),'-element PSF' print,' ' ENDELSE ENDIF ;; Perform main RL iteration. IF twodim THEN BEGIN ;; This section performs RL for 2-dim images. ;; PSF normalization. psfnorm=xrt_fft_2dim_convolution(psf,psf*0+1,nopad=nopad) ;; Starting values for RL iteration. IF (NOT keyword_set(inputohat)) OR n_elements(ohat) EQ 0 THEN BEGIN ;print,'NO Input OHAT!' ohat=image ENDIF FOR i=0,niter-1 DO BEGIN IF keyword_set(verbose) THEN $ print,'Performing 2D iteration '+strtrim(i+1,2)+' of '+strtrim(niter,2) ;; These are the 2 simple steps of the RL algorithm. ihat=xrt_fft_2dim_convolution(psf,ohat,nopad=nopad) ohat*=xrt_fft_2dim_convolution(image/ihat,psf,/corr,nopad=nopad)/psfnorm ENDFOR ENDIF $ ELSE BEGIN ;; This section performs RL for 1-dim images. ;; PSF normalization. psfnorm=xrt_fft_convolution(psf,psf*0+1,nopad=nopad) ;; Starting values for RL iteration. IF (~ keyword_set(inputohat)) OR n_elements(ohat) EQ 0 THEN ohat=image FOR i=0,niter-1 DO BEGIN IF keyword_set(verbose) THEN $ print,'Performing 2D iteration '+strtrim(i+1,2)+' of '+strtrim(niter,2) ;; These are the 2 simple steps of the RL algorithm. ihat=xrt_fft_convolution(psf,ohat,nopad=nopad) ohat*=xrt_fft_convolution(image/ihat,psf,/corr,nopad=nopad)/psfnorm ENDFOR ENDELSE RETURN,abs(ohat) END