public static double[,] Backward(Complex[,] grid, long visibilityCount) { double[,] output = new double[grid.GetLength(0), grid.GetLength(1)]; using (var imageSpace = new AlignedArrayComplex(16, grid.GetLength(0), grid.GetLength(1))) using (var fourierSpace = new AlignedArrayComplex(16, imageSpace.GetSize())) { for (int y = 0; y < grid.GetLength(0); y++) { for (int x = 0; x < grid.GetLength(1); x++) { fourierSpace[y, x] = grid[y, x]; } } DFT.IFFT(fourierSpace, imageSpace, PlannerFlags.Default, Environment.ProcessorCount); for (int y = 0; y < grid.GetLength(0); y++) { for (int x = 0; x < grid.GetLength(1); x++) { output[y, x] = imageSpace[y, x].Real / visibilityCount; } } } return(output); }
public static Complex[,] Forward(float[,] image, double norm = 1.0) { Complex[,] output = new Complex[image.GetLength(0), image.GetLength(1)]; using (var imageSpace = new AlignedArrayComplex(16, image.GetLength(0), image.GetLength(1))) using (var fourierSpace = new AlignedArrayComplex(16, imageSpace.GetSize())) { for (int y = 0; y < image.GetLength(0); y++) { for (int x = 0; x < image.GetLength(1); x++) { imageSpace[y, x] = image[y, x]; } } DFT.FFT(imageSpace, fourierSpace); for (int y = 0; y < image.GetLength(0); y++) { for (int x = 0; x < image.GetLength(1); x++) { output[y, x] = fourierSpace[y, x] / norm; } } } return(output); }
public static float[,] BackwardFloat(Complex[,] image, double norm) { var output = new float[image.GetLength(0), image.GetLength(1)]; using (var imageSpace = new AlignedArrayComplex(16, image.GetLength(0), image.GetLength(1))) using (var fourierSpace = new AlignedArrayComplex(16, imageSpace.GetSize())) { for (int y = 0; y < image.GetLength(0); y++) { for (int x = 0; x < image.GetLength(1); x++) { imageSpace[y, x] = image[y, x]; } } DFT.IFFT(imageSpace, fourierSpace, PlannerFlags.Default, Environment.ProcessorCount); for (int y = 0; y < image.GetLength(0); y++) { for (int x = 0; x < image.GetLength(1); x++) { output[y, x] = (float)(fourierSpace[y, x].Real / norm); } } } return(output); }
public InverseComplexFft(int fftSize) { FftSize = fftSize; Input = new AlignedArrayComplex(16, fftSize); Output = new AlignedArrayComplex(16, fftSize); InverseFft = FftwPlanC2C.Create(Input, Output, DftDirection.Backwards, PlannerFlags.Estimate); }
public static Complex[,] Forward(double[,] image, double norm = 1.0) { Complex[,] output = new Complex[image.GetLength(0), image.GetLength(1)]; using (var imageSpace = new AlignedArrayComplex(16, image.GetLength(0), image.GetLength(1))) using (var fourierSpace = new AlignedArrayComplex(16, imageSpace.GetSize())) { for (int y = 0; y < image.GetLength(0); y++) { for (int x = 0; x < image.GetLength(1); x++) { imageSpace[y, x] = image[y, x]; } } DFT.FFT(imageSpace, fourierSpace, PlannerFlags.Default, Environment.ProcessorCount); for (int y = 0; y < image.GetLength(0); y++) { for (int x = 0; x < image.GetLength(1); x++) { output[y, x] = fourierSpace[y, x] / norm; } } } return(output); }
static void Example2D() { using (var input = new AlignedArrayComplex(16, 64, 16)) using (var output = new AlignedArrayComplex(16, input.GetSize())) { for (int row = 0; row < input.GetLength(0); row++) { for (int col = 0; col < input.GetLength(1); col++) { input[row, col] = (double)row * col / input.Length; } } DFT.FFT(input, output); DFT.IFFT(output, output); for (int row = 0; row < input.GetLength(0); row++) { for (int col = 0; col < input.GetLength(1); col++) { Console.Write((output[row, col].Real / input[row, col].Real / input.Length).ToString("F2").PadLeft(6)); } Console.WriteLine(); } } }
public static float[,] WStackIFFTFloat(List <Complex[, ]> grid, long visibilityCount) { var output = new float[grid[0].GetLength(0), grid[0].GetLength(1)]; using (var imageSpace = new AlignedArrayComplex(16, grid[0].GetLength(0), grid[0].GetLength(1))) using (var fourierSpace = new AlignedArrayComplex(16, imageSpace.GetSize())) { for (int k = 0; k < grid.Count; k++) { Parallel.For(0, grid[0].GetLength(0), (y) => { for (int x = 0; x < grid[0].GetLength(1); x++) { fourierSpace[y, x] = grid[k][y, x]; } }); DFT.IFFT(fourierSpace, imageSpace, PlannerFlags.Default, Environment.ProcessorCount); Parallel.For(0, grid[0].GetLength(0), (y) => { for (int x = 0; x < grid[0].GetLength(1); x++) { output[y, x] += (float)(imageSpace[y, x].Real / visibilityCount); } }); } } return(output); }
public InverseRealFft(int fftSize) { FftSize = fftSize; Waveform = new AlignedArrayDouble(16, fftSize); Spectrum = new AlignedArrayComplex(16, fftSize); InverseFft = FftwPlanRC.Create(Waveform, Spectrum, DftDirection.Backwards, PlannerFlags.Estimate); }
public FFT(int ySize, int xSize, int nCores) { var dims = new int[] { ySize, xSize }; ImageBuffer = new AlignedArrayComplex(16, dims); FourierBuffer = new AlignedArrayComplex(16, dims); fft = FftwPlanC2C.Create(ImageBuffer, FourierBuffer, DftDirection.Forwards, PlannerFlags.Default, nCores); ifft = FftwPlanC2C.Create(FourierBuffer, ImageBuffer, DftDirection.Backwards, PlannerFlags.Default, nCores); }
///<summary> ///This routine casts the image to a format suitable for the FFTW engine /// </summary> /// <param name="im">Image double matrix to be cast to FTTW format</param> /// <returns>A pointer to an AlignedArrayComplex suitable for FFTW engine</returns> private static AlignedArrayComplex CastImageToFFTW(double[,] im) { int m = im.GetLength(0); int n = im.GetLength(1); var ImFFTW = new AlignedArrayComplex(16, m, n); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { ImFFTW[i, j] = im[i, j]; } } return(ImFFTW); }
///<summary> ///This routine casts the Fourier transform complex array to a format suitable for the FFTW engine /// </summary> /// <param name="Y">Spectrum to be sent to FFTW</param> /// <returns>A pointer to an AlignedArrayComplex suitable for FFTW engine</returns> private static AlignedArrayComplex CastSpectrumToFFTW(Complex[,] Y) { int m = Y.GetLength(0); int n = Y.GetLength(1); double S = (double)m * n; var FFTWHandle = new AlignedArrayComplex(16, m, n); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { FFTWHandle[i, j] = Y[i, j] * S; } } return(FFTWHandle); }
public static List <List <Complex[, ]> > Forward(GriddingConstants c, List <List <Complex[, ]> > subgrids) { var output = new List <List <Complex[, ]> >(subgrids.Count); for (int baseline = 0; baseline < subgrids.Count; baseline++) { var blSubgrids = subgrids[baseline]; var blOutput = new List <Complex[, ]>(blSubgrids.Count); for (int subgrid = 0; subgrid < blSubgrids.Count; subgrid++) { var sub = blSubgrids[subgrid]; var outFourier = new Complex[c.SubgridSize, c.SubgridSize]; using (var imageSpace = new AlignedArrayComplex(16, c.SubgridSize, c.SubgridSize)) using (var fourierSpace = new AlignedArrayComplex(16, imageSpace.GetSize())) { //copy for (int i = 0; i < c.SubgridSize; i++) { for (int j = 0; j < c.SubgridSize; j++) { imageSpace[i, j] = sub[i, j]; } } /* * This is not a bug * The original IDG implementation uses the inverse Fourier transform here, even though the * Subgrids are already in image space. */ DFT.IFFT(imageSpace, fourierSpace); var norm = 1.0 / (c.SubgridSize * c.SubgridSize); for (int i = 0; i < c.SubgridSize; i++) { for (int j = 0; j < c.SubgridSize; j++) { outFourier[i, j] = fourierSpace[i, j] * norm; } } } blOutput.Add(outFourier); } output.Add(blOutput); } return(output); }
///<summary> ///This routine casts the output of FFTW engine to a Complex matrix, so the spectrum can be saved ///and manipulated /// </summary> /// <param name="FFTOutput">The FFT spectrum output in FFTW format</param> /// <returns>Spectrum as matrix of double</returns> private static Complex[,] CastFFTWToComplexSpectrum(AlignedArrayComplex FFTOutput) { int m = FFTOutput.GetLength(0); int n = FFTOutput.GetLength(1); double N_spe = (double)m * n; Complex[,] spectrum = new Complex[m, n]; //Initialize spectrum for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { spectrum[i, j] = new Complex(FFTOutput[i, j].Real / N_spe, FFTOutput[i, j].Imaginary / N_spe); } } return(spectrum); }
private bool disposedValue = false; // To detect redundant calls protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { fft.Dispose(); ifft.Dispose(); ImageBuffer.Dispose(); FourierBuffer.Dispose(); } ImageBuffer = null; FourierBuffer = null; disposedValue = true; } }
public static void Shift(AlignedArrayComplex grid) { var n2 = grid.GetLength(0) / 2; for (int i = 0; i < n2; i++) { for (int j = 0; j < n2; j++) { var tmp13 = grid[i, j]; grid[i, j] = grid[i + n2, j + n2]; grid[i + n2, j + n2] = tmp13; var tmp24 = grid[i + n2, j]; grid[i + n2, j] = grid[i, j + n2]; grid[i, j + n2] = tmp24; } } }
public static List <List <Complex[, ]> > Backward(GriddingConstants c, List <List <Complex[, ]> > subgrids) { var output = new List <List <Complex[, ]> >(subgrids.Count); for (int baseline = 0; baseline < subgrids.Count; baseline++) { var blSubgrids = subgrids[baseline]; var blOutput = new List <Complex[, ]>(blSubgrids.Count); for (int subgrid = 0; subgrid < blSubgrids.Count; subgrid++) { var sub = blSubgrids[subgrid]; var outFourier = new Complex[c.SubgridSize, c.SubgridSize]; using (var imageSpace = new AlignedArrayComplex(16, c.SubgridSize, c.SubgridSize)) using (var fourierSpace = new AlignedArrayComplex(16, imageSpace.GetSize())) { //copy for (int i = 0; i < c.SubgridSize; i++) { for (int j = 0; j < c.SubgridSize; j++) { imageSpace[i, j] = sub[i, j]; } } DFT.FFT(imageSpace, fourierSpace); //normalization is done in the Gridder for (int i = 0; i < c.SubgridSize; i++) { for (int j = 0; j < c.SubgridSize; j++) { outFourier[i, j] = fourierSpace[i, j]; } } } blOutput.Add(outFourier); } output.Add(blOutput); } return(output); }
public static cuDoubleComplex[] PerformFft(cuDoubleComplex[] data, int size, TransformDirection direction) { if (cudaAvailable) { return(cuHelper.PerformFFT(data, size, direction)); } else { cuDoubleComplex[] result = new cuDoubleComplex[size * size]; using (var input = new AlignedArrayComplex(16, size, size)) using (var output = new AlignedArrayComplex(16, input.GetSize())) { for (int i = 0; i < input.GetLength(0); i++) { for (int j = 0; j < input.GetLength(1); j++) { input[i, j] = new Complex(data[i * size + j].real, data[i * size + j].imag); } } if (direction == TransformDirection.Forward) { DFT.FFT(input, output); } else { DFT.IFFT(input, output); } for (int i = 0; i < input.GetLength(0); i++) { for (int j = 0; j < input.GetLength(1); j++) { result[i * size + j].real = output[i, j].Real; result[i * size + j].imag = output[i, j].Imaginary; } } } return(result); } }
/// <summary> /// Routine to simulate motion blur, given the amount of motion blur (it can be any real number!) /// and the direction of motion blur. /// </summary> /// <param name="im">Input double matrix image</param> /// <param name="W">Amount of motion blur i.e. 1.3</param> /// <param name="alpha">Motion blur direction angle (in degrees) - clockwise</param> /// <param name="Parallelize">Boolean to state if you want to parallelize spectral convolution</param> /// <returns>The blurred image as double matrix</returns> public static double[,] SimulateMotionBlurRoutine(double[,] im, double W, double alpha, bool Parallelize) { int m = im.GetLength(0); int n = im.GetLength(1); double[,] outputMat = new double[m, n]; //Initialize FFTW arrays var ImgFFTWInput = CastImageToFFTW(im); AlignedArrayComplex FFTWOutputArray = new AlignedArrayComplex(16, ImgFFTWInput.GetSize()); AlignedArrayComplex FFTWConvOutputArray = new AlignedArrayComplex(16, ImgFFTWInput.GetSize()); //Step 1 - Compute image spectrum DFT.FFT(ImgFFTWInput, FFTWOutputArray); var ImSpectrum = CastFFTWToComplexSpectrum(FFTWOutputArray); //Step 2 - Generate Optical Transfer function (OTF) var GridU = GenerateFFTMeshGrid(m, n, 1); var GridV = GenerateFFTMeshGrid(m, n, 2); Complex[,] MB_OTF = new Complex[m, n]; //Initialize OTF Double f_indx = new double(); //kernel effective frequency for (int u = 0; u < m; u++) { for (int v = 0; v < n; v++) { double f_u = GridU[u, v] / m; double f_v = GridV[u, v] / n; f_indx = Math.Cos(alpha / 180 * Math.PI) * f_u + Math.Sin(alpha / 180 * Math.PI) * f_v; MB_OTF[u, v] = new Complex(Sinc(W * f_indx), 0); } } //Step 3 - Spectral convolution Complex[,] SpecConvolution = new Complex[m, n]; if (Parallelize) { Parallel.For(0, m, u => { for (int v = 0; v < n; v++) { SpecConvolution[u, v] = Complex.Multiply(MB_OTF[u, v], ImSpectrum[u, v]); } }); } else { for (int u = 0; u < m; u++) { for (int v = 0; v < n; v++) { SpecConvolution[u, v] = Complex.Multiply(MB_OTF[u, v], ImSpectrum[u, v]); } } } //Step 4 - Inverse fourier transform to get the blurred image var FFTWSpecConvolution = CastSpectrumToFFTW(SpecConvolution); DFT.IFFT(FFTWSpecConvolution, FFTWConvOutputArray); var ConvOutputArray = CastFFTWToComplexSpectrum(FFTWConvOutputArray); //Just doing this to get the real part of IFFT if (Parallelize) { Parallel.For(0, m, u => { for (int v = 0; v < n; v++) { outputMat[u, v] = ConvOutputArray[u, v].Magnitude; } }); } else { for (int u = 0; u < m; u++) { for (int v = 0; v < n; v++) { outputMat[u, v] = ConvOutputArray[u, v].Magnitude; } } } //Print wisdom DFT.Wisdom.Export("exp_wis.txt"); //Try to clear out as much memory as I can FFTWOutputArray.Dispose(); ImgFFTWInput.Dispose(); FFTWConvOutputArray.Dispose(); GC.Collect(); return(outputMat); }