public static void Run() { //var frequencies = FitsIO.ReadFrequencies(@"C:\Users\Jon\github\p9-data\small\fits\simulation_point\freq.fits"); //var uvw = FitsIO.ReadUVW(@"C:\Users\Jon\github\p9-data\small\fits\simulation_point\uvw.fits"); var frequencies = FitsIO.ReadFrequencies(@"C:\dev\GitHub\p9-data\small\fits\simulation_point\freq.fits"); var uvw = FitsIO.ReadUVW(@"C:\dev\GitHub\p9-data\small\fits\simulation_point\uvw.fits"); var flags = new bool[uvw.GetLength(0), uvw.GetLength(1), frequencies.Length]; //completely unflagged dataset var visibilitiesCount = flags.Length; int gridSize = 64; int subgridsize = 16; int kernelSize = 8; int max_nr_timesteps = 64; double cellSize = 2.0 / 3600.0 * PI / 180.0; var c = new GriddingConstants(visibilitiesCount, gridSize, subgridsize, kernelSize, max_nr_timesteps, (float)cellSize, 1, 0.0f); var metadata = Partitioner.CreatePartition(c, uvw, frequencies); var psfGrid = IDG.GridPSF(c, metadata, uvw, flags, frequencies); var psf = FFT.Backward(psfGrid, c.VisibilitiesCount); FFT.Shift(psf); var maxPsf = psf[gridSize / 2, gridSize / 2]; for (int i = 0; i < psf.GetLength(0); i++) { for (int j = 0; j < psf.GetLength(1); j++) { psf[i, j] = psf[i, j] / maxPsf; } } FitsIO.Write(psf, "psf.fits"); var truth = new double[64, 64]; //truth[40, 50] = 1.5; truth[0, 0] = 1.7; var dirty = ConvolveFFTPadded(truth, psf); FitsIO.Write(truth, "truth.fits"); FitsIO.Write(dirty, "dirty.fits"); var psf2 = ConvolveFFT(psf, psf); var b = ConvolveFFTPadded(dirty, psf); var a = psf2[gridSize / 2, gridSize / 2]; /* * var integral = CalcPSf2Integral(psf); * FitsIO.Write(integral, "psfIntegral.fits"); * var c0 = new double[64, 64]; * var qY = 0; * var qX = 0; * c0[qY, qX] = 1.0; * c0 = Convolve(c0, psf); * FitsIO.Write(c0, "cx0.fits"); * var cx = ConvolveFFT(c0, psf); * FitsIO.Write(cx, "cx1.fits"); * var a2 = cx[qY, qX]; * var res = QueryIntegral(integral, qY, qX);*/ var x = new double[gridSize, gridSize]; //Deconv(x, dirty, psf, psf2, a, 0.0); var dCopy = new double[gridSize, gridSize]; for (int i = 0; i < b.GetLength(0); i++) { for (int j = 0; j < b.GetLength(1); j++) { dCopy[i, j] = dirty[i, j]; } } var x2 = new double[gridSize, gridSize]; var converged = GreedyCD.Deconvolve2(x2, dirty, psf, 0.0, 1.0, 500, dCopy); }
public static bool Deconvolve2(double[,] xImage, double[,] res, double[,] psf, double lambda, double alpha, Rectangle rec, int maxIteration = 100, double[,] dirtyCopy = null) { var yPsfHalf = psf.GetLength(0) / 2; var xPsfHalf = psf.GetLength(1) / 2; var integral = CommonDeprecated.PSF.CalcPSFScan(psf); var resPadded = new double[res.GetLength(0) + psf.GetLength(0), res.GetLength(1) + psf.GetLength(1)]; for (int y = 0; y < res.GetLength(0); y++) { for (int x = 0; x < res.GetLength(1); x++) { resPadded[y + yPsfHalf, x + xPsfHalf] = res[y, x]; } } //invert the PSF, since we actually do want to correlate the psf with the residuals. (The FFT already inverts the psf, so we need to invert it again to not invert it. Trust me.) var psfPadded = new double[res.GetLength(0) + psf.GetLength(0), res.GetLength(1) + psf.GetLength(1)]; var psfYOffset = res.GetLength(0) / 2; var psfXOffset = res.GetLength(1) / 2; for (int y = 0; y < psf.GetLength(0); y++) { for (int x = 0; x < psf.GetLength(1); x++) { psfPadded[y + psfYOffset + 1, x + psfXOffset + 1] = psf[psf.GetLength(0) - y - 1, psf.GetLength(1) - x - 1]; } } FFT.Shift(psfPadded); var PSFPadded = FFT.Forward(psfPadded, 1.0); DeconvolveGreedy2(xImage, resPadded, res, psf, PSFPadded, integral, lambda, alpha, rec, 100); var xCummulatedDiff = new double[xImage.GetLength(0), xImage.GetLength(1)]; int iter = 0; bool converged = false; double epsilon = 1e-4; double objective = double.MaxValue; while (!converged & iter < maxIteration) { var oOld = objective; objective = GreedyCD.CalcElasticNetObjective(xImage, res, integral, lambda, alpha, rec.Y, rec.X); objective += GreedyCD.CalcDataObjective(resPadded, res, yPsfHalf, yPsfHalf); Console.WriteLine("Objective \t" + objective); if (oOld < objective) { Console.Write("error"); } var RES = FFT.Forward(resPadded, 1.0); var B = Common.Fourier2D.Multiply(RES, PSFPadded); var b = FFT.Backward(B, (double)(B.GetLength(0) * B.GetLength(1))); var activeSet = new List <Tuple <int, int> >(); for (int y = rec.Y; y < rec.YLength; y++) { for (int x = rec.X; x < rec.XLength; x++) { var yLocal = y - rec.Y; var xLocal = x - rec.X; var currentA = CommonDeprecated.PSF.QueryScan(integral, y, x, res.GetLength(0), res.GetLength(1)); var old = xImage[yLocal, xLocal]; var xTmp = old + b[y + yPsfHalf, x + xPsfHalf] / currentA; xTmp = CommonDeprecated.ShrinkElasticNet(xTmp, lambda, alpha); var xDiff = old - xTmp; if (Math.Abs(xDiff) > epsilon) { activeSet.Add(new Tuple <int, int>(y, x)); } } } //active set iterations Console.WriteLine("--------------------count:" + activeSet.Count + "------------------"); converged = activeSet.Count == 0; bool activeSetConverged = activeSet.Count == 0; var innerMax = 40; var innerIter = 0; while (!activeSetConverged & innerIter <= innerMax) { var oTest = GreedyCD.CalcElasticNetObjective(xImage, res, integral, lambda, alpha, rec.Y, rec.X); oTest += GreedyCD.CalcDataObjective(resPadded, res, yPsfHalf, yPsfHalf); activeSetConverged = true; var delete = new List <Tuple <int, int> >(); foreach (var pixel in activeSet) { var y = pixel.Item1; var x = pixel.Item2; var yLocal = y - rec.Y; var xLocal = x - rec.X; var xOld = xImage[yLocal, xLocal]; var currentB = CalculateB(resPadded, res, psf, y, x); //calculate minimum of parabola, eg -2b/a var xTmp = xOld + currentB / CommonDeprecated.PSF.QueryScan(integral, y, x, res.GetLength(0), res.GetLength(1)); xTmp = GreedyCD.ShrinkPositive(xTmp, lambda * alpha) / (1 + lambda * (1 - alpha)); var xDiff = xOld - xTmp; if (Math.Abs(xDiff) > epsilon) { activeSetConverged = false; //Console.WriteLine(Math.Abs(xOld - xTmp) + "\t" + y + "\t" + x); xImage[yLocal, xLocal] = xTmp; xCummulatedDiff[yLocal, xLocal] += xDiff; GreedyCD.UpdateResiduals2(resPadded, res, psf, y, x, xDiff, yPsfHalf, xPsfHalf); } else if (xTmp == 0.0) { // zero, remove from active set activeSetConverged = false; xImage[yLocal, xLocal] = 0.0; xCummulatedDiff[yLocal, xLocal] += xOld; GreedyCD.UpdateResiduals2(resPadded, res, psf, y, x, xDiff, yPsfHalf, xPsfHalf); delete.Add(pixel); //Console.WriteLine("drop pixel \t" + xTmp + "\t" + y + "\t" + x); } } innerIter++; } /* * foreach (var pixel in delete) * activeSet.Remove(pixel); * * //exchange with other nodes * var allXDiff = new List<PixelExchange>(); * for (int y = 0; y < xCummulatedDiff.GetLength(0); y++) * for (int x = 0; x < xCummulatedDiff.GetLength(1); x++) * { * if (xCummulatedDiff[y, x] > 0.0) * { * var p = new PixelExchange(); * p.Rank = comm.Rank; * p.Y = rec.Y + y; * p.X = rec.X + x; * p.Value = xCummulatedDiff[y, x]; * allXDiff.Add(p); * xCummulatedDiff[y, x] = 0.0; * } * } * * var allNonZeros = comm.Allreduce(allXDiff, (aC, bC) => * { * aC.AddRange(bC); * return aC; * }); * * foreach (var p in allXDiff) * if (p.Rank != comm.Rank) * GreedyCD.UpdateResiduals2(resPadded, res, psf, p.Y, p.X, p.Value, yPsfHalf, xPsfHalf);*/ RES = FFT.Forward(resPadded, 1.0); B = Common.Fourier2D.Multiply(RES, PSFPadded); b = FFT.Backward(B, (double)(B.GetLength(0) * B.GetLength(1))); iter++; } //copy back the residuals for (int y = 0; y < res.GetLength(0); y++) { for (int x = 0; x < res.GetLength(1); x++) { res[y, x] = resPadded[y + yPsfHalf, x + xPsfHalf]; } } return(converged); }
public static bool Deconvolve(double[,] xImage, double[,] res, double[,] psf, double lambda, double alpha, int maxIteration = 100, double[,] dirtyCopy = null) { var yPsfHalf = psf.GetLength(0) / 2; var xPsfHalf = psf.GetLength(1) / 2; var integral = CommonDeprecated.PSF.CalcPSFScan(psf); var resPadded = new double[res.GetLength(0) + psf.GetLength(0), res.GetLength(1) + psf.GetLength(1)]; for (int y = 0; y < res.GetLength(0); y++) { for (int x = 0; x < res.GetLength(1); x++) { resPadded[y + yPsfHalf, x + xPsfHalf] = res[y, x]; } } //invert the PSF, since we actually do want to correlate the psf with the residuals. (The FFT already inverts the psf, so we need to invert it again to not invert it. Trust me.) var psfPadded = new double[res.GetLength(0) + psf.GetLength(0), res.GetLength(1) + psf.GetLength(1)]; var psfYOffset = res.GetLength(0) / 2; var psfXOffset = res.GetLength(1) / 2; for (int y = 0; y < psf.GetLength(0); y++) { for (int x = 0; x < psf.GetLength(1); x++) { psfPadded[y + psfYOffset + 1, x + psfXOffset + 1] = psf[psf.GetLength(0) - y - 1, psf.GetLength(1) - x - 1]; } } FFT.Shift(psfPadded); var PSFPaddedCorr = FFT.Forward(psfPadded, 1.0); var psfPaddedConv = new double[res.GetLength(0) + psf.GetLength(0), res.GetLength(1) + psf.GetLength(1)]; for (int y = 0; y < psf.GetLength(0); y++) { for (int x = 0; x < psf.GetLength(1); x++) { psfPaddedConv[y + psfYOffset + 1, x + psfXOffset + 1] = psf[y, x]; } } FFT.Shift(psfPaddedConv); var PSFPaddedConv = FFT.Forward(psfPaddedConv, 1.0); DeconvolveGreedy(xImage, resPadded, res, psf, PSFPaddedCorr, integral, lambda, alpha, 100); var xCummulatedDiff = new double[res.GetLength(0) + psf.GetLength(0), res.GetLength(1) + psf.GetLength(1)]; int iter = 0; bool converged = false; double epsilon = 1e-6; while (!converged & iter < maxIteration) { var RES = FFT.Forward(resPadded, 1.0); var B = Common.Fourier2D.Multiply(RES, PSFPaddedCorr); var b = FFT.Backward(B, (double)(B.GetLength(0) * B.GetLength(1))); var activeSet = new List <Tuple <int, int> >(); for (int y = 0; y < xImage.GetLength(0); y++) { for (int x = 0; x < xImage.GetLength(1); x++) { var currentA = CommonDeprecated.PSF.QueryScan(integral, y, x, xImage.GetLength(0), xImage.GetLength(1)); var old = xImage[y, x]; var xTmp = old + b[y + yPsfHalf, x + xPsfHalf] / currentA; xTmp = GreedyCD.ShrinkPositive(xTmp, lambda * alpha) / (1 + lambda * (1 - alpha)); var xDiff = old - xTmp; if (Math.Abs(xDiff) > epsilon / 50.0) { activeSet.Add(new Tuple <int, int>(y, x)); } } } var objective = GreedyCD.CalcElasticNetObjective(xImage, res, integral, lambda, alpha, 0, 0); objective += GreedyCD.CalcDataObjective(resPadded, res, yPsfHalf, yPsfHalf); Console.WriteLine("Objective test \t" + objective); Console.WriteLine("--------------------count:" + activeSet.Count + "------------------"); //active set iterations converged = activeSet.Count == 0; bool activeSetConverged = activeSet.Count == 0; var innerMax = 2000; var innerIter = 0; Randomize(activeSet); while (!activeSetConverged & innerIter <= innerMax) { activeSetConverged = true; var delete = new List <Tuple <int, int> >(); var i = 0; foreach (var pixel in activeSet) { var y = pixel.Item1; var x = pixel.Item2; var xOld = xImage[y, x]; var currentB = b[y + yPsfHalf, x + xPsfHalf]; var xTmp = xOld + currentB / CommonDeprecated.PSF.QueryScan(integral, y, x, xImage.GetLength(0), xImage.GetLength(1));; xTmp = GreedyCD.ShrinkPositive(xTmp, lambda * alpha) / (1 + lambda * (1 - alpha)); var xDiff = (xOld - xTmp) / 50.0; if (Math.Abs(xDiff) > epsilon / 50.0) { activeSetConverged = false; //Console.WriteLine(Math.Abs(xOld - xTmp) + "\t" + y + "\t" + x); xImage[y, x] = xTmp; xCummulatedDiff[y + yPsfHalf, x + xPsfHalf] += xDiff; } else if (xTmp == 0.0) { //approximately zero, remove from active set activeSetConverged = false; xImage[y, x] = 0.0; xCummulatedDiff[y + yPsfHalf, x + xPsfHalf] += xOld; delete.Add(pixel); //Console.WriteLine("drop pixel \t" + xTmp + "\t" + y + "\t" + x); } if (i % 50 == 0) { var Xdiff = FFT.Forward(xCummulatedDiff, 1.0); var RESdiff = Common.Fourier2D.Multiply(Xdiff, PSFPaddedConv); var resDiff = FFT.Backward(RESdiff, (double)(RESdiff.GetLength(0) * RESdiff.GetLength(1))); for (int y2 = 0; y2 < res.GetLength(0); y2++) { for (int x2 = 0; x2 < res.GetLength(1); x2++) { resPadded[y2 + yPsfHalf, x2 + xPsfHalf] += resDiff[y2 + yPsfHalf, x2 + xPsfHalf]; } } xCummulatedDiff = new double[res.GetLength(0) + psf.GetLength(0), res.GetLength(1) + psf.GetLength(1)]; RES = FFT.Forward(resPadded, 1.0); B = Common.Fourier2D.Multiply(RES, PSFPaddedCorr); b = FFT.Backward(B, (double)(B.GetLength(0) * B.GetLength(1))); var objective2 = GreedyCD.CalcElasticNetObjective(xImage, res, integral, lambda, alpha, 0, 0); objective2 += GreedyCD.CalcDataObjective(resPadded, res, yPsfHalf, yPsfHalf); Console.WriteLine("Objective test \t" + objective2); } i++; } var Xdiff2 = FFT.Forward(xCummulatedDiff, 1.0); var RESdiff2 = Common.Fourier2D.Multiply(Xdiff2, PSFPaddedConv); var resDiff2 = FFT.Backward(RESdiff2, (double)(RESdiff2.GetLength(0) * RESdiff2.GetLength(1))); for (int y2 = 0; y2 < res.GetLength(0); y2++) { for (int x2 = 0; x2 < res.GetLength(1); x2++) { resPadded[y2 + yPsfHalf, x2 + xPsfHalf] += resDiff2[y2 + yPsfHalf, x2 + xPsfHalf]; } } xCummulatedDiff = new double[res.GetLength(0) + psf.GetLength(0), res.GetLength(1) + psf.GetLength(1)]; RES = FFT.Forward(resPadded, 1.0); B = Common.Fourier2D.Multiply(RES, PSFPaddedCorr); b = FFT.Backward(B, (double)(B.GetLength(0) * B.GetLength(1))); var objective3 = GreedyCD.CalcElasticNetObjective(xImage, res, integral, lambda, alpha, 0, 0); objective3 += GreedyCD.CalcDataObjective(resPadded, res, yPsfHalf, yPsfHalf); Console.WriteLine("Objective done iteration \t" + objective3); //FitsIO.Write(resPadded, "debugResiduals.fits"); /* * foreach (var pixel in activeSet) * { * //serial descent * var y = pixel.Item1; * var x = pixel.Item2; * var xOld = xImage[y, x]; * var currentB = CalculateB(resPadded, xImage, psf, y, x); * * //calculate minimum of parabola, eg -2b/a * var xTmp = xOld + currentB / Common.PSF.QueryScan(integral, y, x, xImage.GetLength(0), xImage.GetLength(1)); ; * xTmp = GreedyCD.ShrinkPositive(xTmp, lambda * alpha) / (1 + lambda * (1 - alpha)); * var xDiff = xOld - xTmp; * * * if (Math.Abs(xDiff) > epsilon) * { * activeSetConverged = false; * //Console.WriteLine(Math.Abs(xOld - xTmp) + "\t" + y + "\t" + x); * xImage[y, x] = xTmp; * xCummulatedDiff[y, x] += xDiff; * GreedyCD.UpdateResiduals2(resPadded, xImage, psf, y, x, xDiff, yPsfHalf, xPsfHalf); * } * else if (xTmp == 0.0) * { * //approximately zero, remove from active set * activeSetConverged = false; * xImage[y, x] = 0.0; * xCummulatedDiff[y, x] += xOld; * GreedyCD.UpdateResiduals2(resPadded, xImage, psf, y, x, xDiff, yPsfHalf, xPsfHalf); * delete.Add(pixel); * //Console.WriteLine("drop pixel \t" + xTmp + "\t" + y + "\t" + x); * } * }*/ innerIter++; foreach (var pixel in delete) { activeSet.Remove(pixel); } } RES = FFT.Forward(resPadded, 1.0); B = Common.Fourier2D.Multiply(RES, PSFPaddedCorr); b = FFT.Backward(B, (double)(B.GetLength(0) * B.GetLength(1))); iter++; } //copy back the residuals for (int y = 0; y < res.GetLength(0); y++) { for (int x = 0; x < res.GetLength(1); x++) { res[y, x] = resPadded[y + yPsfHalf, x + xPsfHalf]; } } return(converged); }
public static bool DeconvolveGreedy2(double[,] xImage, double[,] resPadded, double[,] res, double[,] psf, Complex[,] PSFPadded, double[,] integral, double lambda, double alpha, Rectangle rec, int maxIteration = 100, double[,] dirtyCopy = null) { var yPsfHalf = psf.GetLength(0) / 2; var xPsfHalf = psf.GetLength(1) / 2; var RES = FFT.Forward(resPadded, 1.0); var B = Common.Fourier2D.Multiply(RES, PSFPadded); var b = FFT.Backward(B, (double)(B.GetLength(0) * B.GetLength(1))); double objective = GreedyCD.CalcElasticNetObjective(xImage, res, integral, lambda, alpha, rec.Y, rec.X); objective += GreedyCD.CalcDataObjective(resPadded, res, yPsfHalf, yPsfHalf); int iter = 0; bool converged = false; double epsilon = 1e-4; while (!converged & iter < maxIteration) { var yPixel = -1; var xPixel = -1; var xMax = 0.0; var xNew = 0.0; for (int y = rec.Y; y < rec.YLength; y++) { for (int x = rec.X; x < rec.XLength; x++) { var yLocal = y - rec.Y; var xLocal = x - rec.X; var currentA = CommonDeprecated.PSF.QueryScan(integral, y, x, res.GetLength(0), res.GetLength(1)); var old = xImage[yLocal, xLocal]; var xTmp = old + b[y + yPsfHalf, x + xPsfHalf] / currentA; xTmp = GreedyCD.ShrinkPositive(xTmp, lambda * alpha) / (1 + lambda * (1 - alpha)); var xDiff = old - xTmp; if (Math.Abs(xDiff) > xMax) { yPixel = y; xPixel = x; xMax = Math.Abs(xDiff); xNew = xTmp; } } } //exchange max converged = Math.Abs(xMax) < epsilon; if (!converged) { var yLocal2 = yPixel - rec.Y; var xLocal2 = xPixel - rec.X; var xOld = xImage[yLocal2, xLocal2]; xImage[yLocal2, xLocal2] = xNew; Console.WriteLine(iter + "\t" + Math.Abs(xOld - xNew) + "\t" + yLocal2 + "\t" + xLocal2); GreedyCD.UpdateResiduals2(resPadded, res, psf, yPixel, xPixel, xOld - xNew, yPsfHalf, xPsfHalf); RES = FFT.Forward(resPadded, 1.0); B = Common.Fourier2D.Multiply(RES, PSFPadded); b = FFT.Backward(B, (double)(B.GetLength(0) * B.GetLength(1))); iter++; } } return(converged); }
public static bool Deconvolve2(double[,] xImage, double[,] res, double[,] psf, double lambda, double alpha, int maxIteration = 100, double[,] dirtyCopy = null) { var yPsfHalf = psf.GetLength(0) / 2; var xPsfHalf = psf.GetLength(1) / 2; var integral = CommonDeprecated.PSF.CalcPSFScan(psf); var resPadded = new double[res.GetLength(0) + psf.GetLength(0), res.GetLength(1) + psf.GetLength(1)]; for (int y = 0; y < res.GetLength(0); y++) { for (int x = 0; x < res.GetLength(1); x++) { resPadded[y + yPsfHalf, x + xPsfHalf] = res[y, x]; } } //invert the PSF, since we actually do want to correlate the psf with the residuals. (The FFT already inverts the psf, so we need to invert it again to not invert it. Trust me.) var psfPadded = new double[res.GetLength(0) + psf.GetLength(0), res.GetLength(1) + psf.GetLength(1)]; var psfYOffset = res.GetLength(0) / 2; var psfXOffset = res.GetLength(1) / 2; for (int y = 0; y < psf.GetLength(0); y++) { for (int x = 0; x < psf.GetLength(1); x++) { psfPadded[y + psfYOffset + 1, x + psfXOffset + 1] = psf[psf.GetLength(0) - y - 1, psf.GetLength(1) - x - 1]; } } FFT.Shift(psfPadded); var RES = FFT.Forward(resPadded, 1.0); var PSFPadded = FFT.Forward(psfPadded, 1.0); var B = Common.Fourier2D.Multiply(RES, PSFPadded); var b = FFT.Backward(B, (double)(B.GetLength(0) * B.GetLength(1))); double objective = 0; objective += CalcElasticNetObjective(xImage, res, integral, lambda, alpha, 0, 0); objective += CalcDataObjective(res); Console.WriteLine("Objective \t" + objective); int iter = 0; bool converged = false; double epsilon = 1e-4; while (!converged & iter < maxIteration) { var yPixel = -1; var xPixel = -1; var maxImprov = 0.0; var xNew = 0.0; for (int y = 0; y < res.GetLength(0); y++) { for (int x = 0; x < res.GetLength(1); x++) { var currentA = CommonDeprecated.PSF.QueryScan(integral, y, x, res.GetLength(0), res.GetLength(1)); var old = xImage[y, x]; var xTmp = old + b[y + yPsfHalf, x + xPsfHalf] / currentA; xTmp = GreedyCD.ShrinkPositive(xTmp, lambda * alpha) / (1 + lambda * (1 - alpha)); var xDiff = old - xTmp; var oImprov = EstimateObjectiveImprovement2(resPadded, res, psf, y, x, xDiff); var lambdaA = lambda * 2 * currentA; oImprov += lambdaA * GreedyCD.ElasticNetRegularization(old, alpha); oImprov -= lambdaA * GreedyCD.ElasticNetRegularization(xTmp, alpha); if (oImprov > maxImprov) { yPixel = y; xPixel = x; maxImprov = oImprov; xNew = xTmp; } } } var xOld = xImage[yPixel, xPixel]; converged = maxImprov < epsilon; if (!converged) { xImage[yPixel, xPixel] = xNew; objective -= maxImprov; Console.WriteLine(iter + "\t" + Math.Abs(xOld - xNew) + "\t" + yPixel + "\t" + xPixel + "\t" + objective); var debug = EstimateObjectiveImprovement2(resPadded, res, psf, yPixel, xPixel, xOld - xNew); UpdateResiduals2(resPadded, res, psf, yPixel, xPixel, xOld - xNew, yPsfHalf, xPsfHalf); RES = FFT.Forward(resPadded, 1.0); B = Common.Fourier2D.Multiply(RES, PSFPadded); b = FFT.Backward(B, (double)(B.GetLength(0) * B.GetLength(1))); iter++; } } return(converged); }