public static Tuple <int, int, double>[] GetMaxBlocks(float[,] bMap, float[,] xImage, double lipschitz, float lambda, float alpha, int yBlockSize, int xBlockSize, int theta) { var yBlocks = bMap.GetLength(0) / yBlockSize; var xBlocks = bMap.GetLength(1) / xBlockSize; var tmp = new List <Tuple <int, int, double> >(yBlocks * xBlocks); for (int i = 0; i < yBlocks; i++) { for (int j = 0; j < xBlocks; j++) { int yIdx = i * yBlockSize; int xIdx = j * xBlockSize; var sum = 0.0; for (int y = yIdx; y < yIdx + yBlockSize; y++) { for (int x = xIdx; x < xIdx + xBlockSize; x++) { var opt = bMap[y, x] / lipschitz; var shrink = CommonDeprecated.ShrinkElasticNet(xImage[y, x] + opt, lambda, alpha); sum += Math.Abs(shrink - xImage[y, x]); } } tmp.Add(new Tuple <int, int, double>(i, j, sum)); } } tmp.Sort((x, y) => x.Item3.CompareTo(y.Item3)); var output = new Tuple <int, int, double> [theta]; for (int i = 0; i < theta; i++) { output[i] = tmp[tmp.Count - i - 1]; } return(output); }
private static Tuple <int, int, double> GetMaxBlock(float[,] bMap, float[,] xImage, double lipschitz, float lambda, float alpha, int yBlockSize, int xBlockSize) { var yBlocks = bMap.GetLength(0) / yBlockSize; var xBlocks = bMap.GetLength(1) / xBlockSize; var maxSum = 0.0; var yBlockIdx = -1; var xBlockIdx = -1; for (int i = 0; i < yBlocks; i++) { for (int j = 0; j < xBlocks; j++) { int yIdx = i * yBlockSize; int xIdx = j * xBlockSize; var sum = 0.0; for (int y = yIdx; y < yIdx + yBlockSize; y++) { for (int x = xIdx; x < xIdx + xBlockSize; x++) { var opt = bMap[y, x] / lipschitz; var shrink = CommonDeprecated.ShrinkElasticNet(xImage[y, x] + opt, lambda, alpha); sum += Math.Abs(shrink - xImage[y, x]); } } if (maxSum < sum) { maxSum = sum; yBlockIdx = i; xBlockIdx = j; } } } return(new Tuple <int, int, double>(yBlockIdx, xBlockIdx, maxSum)); }
public static bool Deconvolve2(double[,] xImage, double[,] residuals, double[,] psf, double lambda, double alpha, Random random, int maxIteration = 100, double epsilon = 1e-4) { var xImage2 = ToFloatImage(xImage); var PSFConvolution = CommonDeprecated.PSF.CalcPaddedFourierConvolution(psf, residuals.GetLength(0), residuals.GetLength(1)); var PSFCorrelation = CommonDeprecated.PSF.CalculateFourierCorrelation(psf, residuals.GetLength(0), residuals.GetLength(1)); var PSFSquared = Fourier2D.Multiply(PSFConvolution, PSFCorrelation); var bMapCalculator = new PaddedConvolver(PSFCorrelation, new Rectangle(0, 0, psf.GetLength(0), psf.GetLength(1))); var resUpdateCalculator = new PaddedConvolver(PSFConvolution, new Rectangle(0, 0, psf.GetLength(0), psf.GetLength(1))); var bMapUpdateCalculator = new PaddedConvolver(PSFSquared, new Rectangle(0, 0, psf.GetLength(0), psf.GetLength(1))); var yBlockSize = 2; var xBlockSize = 2; var bMap = ToFloatImage(residuals); bMapCalculator.ConvolveInPlace(bMap); FitsIO.Write(bMap, "bmapFirst.fits"); var xDiff = new float[xImage.GetLength(0), xImage.GetLength(1)]; var lipschitz = ApproximateLipschitz(psf, yBlockSize, xBlockSize); var startL2 = NaiveGreedyCD.CalcDataObjective(residuals); var iter = 0; while (iter < maxIteration) { var yB = random.Next(xImage.GetLength(0) / yBlockSize); var xB = random.Next(xImage.GetLength(1) / xBlockSize); //yB = 64 / yBlockSize; //xB = 64 / xBlockSize; var block = CopyFrom(bMap, yB, xB, yBlockSize, xBlockSize); //var optimized = block * blockInversion; var update = block / lipschitz; var xOld = CopyFrom(xImage2, yB, xB, yBlockSize, xBlockSize); var optimized = xOld + update; //shrink bool containsNonZero = false; for (int i = 0; i < optimized.Count; i++) { optimized[i] = CommonDeprecated.ShrinkElasticNet(optimized[i], lambda, alpha); containsNonZero |= (optimized[i] - xOld[i]) != 0.0; } var optDiff = optimized - xOld; if (containsNonZero) { AddInto(xDiff, optDiff, yB, xB, yBlockSize, xBlockSize); AddInto(xImage2, optDiff, yB, xB, yBlockSize, xBlockSize); //FitsIO.Write(xImage2, "xImageBlock.fits"); //FitsIO.Write(xDiff, "xDiff.fits"); //update b-map bMapUpdateCalculator.ConvolveInPlace(xDiff); //FitsIO.Write(xDiff, "bMapUpdate.fits"); for (int i = 0; i < xDiff.GetLength(0); i++) { for (int j = 0; j < xDiff.GetLength(1); j++) { bMap[i, j] -= xDiff[i, j]; xDiff[i, j] = 0; } } //FitsIO.Write(bMap, "bMap2.fits"); //calc residuals for debug purposes AddInto(xDiff, optDiff, yB, xB, yBlockSize, xBlockSize); resUpdateCalculator.ConvolveInPlace(xDiff); //FitsIO.Write(xDiff, "residualsUpdate.fits"); for (int i = 0; i < xDiff.GetLength(0); i++) { for (int j = 0; j < xDiff.GetLength(1); j++) { residuals[i, j] -= xDiff[i, j]; xDiff[i, j] = 0; } } //FitsIO.Write(residuals, "residuals2.fits"); var l2 = NaiveGreedyCD.CalcDataObjective(residuals); Console.WriteLine(l2); } iter++; } for (int i = 0; i < xImage.GetLength(0); i++) { for (int j = 0; j < xImage.GetLength(1); j++) { xImage[i, j] = xImage2[i, j]; } } return(false); }
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 Deconvolve2(double[,] xImage, double[,] residuals, double[,] psf, double lambda, double alpha, int blockSize, int maxIteration = 100, double epsilon = 1e-4) { var xImage2 = ToFloatImage(xImage); var PSFConvolution = CommonDeprecated.PSF.CalcPaddedFourierConvolution(psf, residuals.GetLength(0), residuals.GetLength(1)); var PSFCorrelation = CommonDeprecated.PSF.CalculateFourierCorrelation(psf, residuals.GetLength(0), residuals.GetLength(1)); var PSFSquared = Fourier2D.Multiply(PSFConvolution, PSFCorrelation); var bMapCalculator = new PaddedConvolver(PSFCorrelation, new Rectangle(0, 0, psf.GetLength(0), psf.GetLength(1))); var resUpdateCalculator = new PaddedConvolver(PSFConvolution, new Rectangle(0, 0, psf.GetLength(0), psf.GetLength(1))); var bMapUpdateCalculator = new PaddedConvolver(PSFSquared, new Rectangle(0, 0, psf.GetLength(0), psf.GetLength(1))); var yBlockSize = blockSize; var xBlockSize = blockSize; var bMap = ToFloatImage(residuals); bMapCalculator.ConvolveInPlace(bMap); var xDiff = new float[xImage.GetLength(0), xImage.GetLength(1)]; var startL2 = NaiveGreedyCD.CalcDataObjective(residuals); var theta = 2; //theta, also number of processors. var degreeOfSep = RandomCD.CountNonZero(psf); var blockCount = xImage.Length / (yBlockSize * xBlockSize); var beta = 1.0 + (degreeOfSep - 1.0) * (theta - 1.0) / (Math.Max(1.0, (blockCount - 1))); //arises from E.S.O of theta-nice sampling. Look at the original PCDM Paper for the explanation //Theta-nice sampling: take theta number of random pixels var lipschitz = RandomBlockCD2.ApproximateLipschitz(psf, yBlockSize, xBlockSize); lipschitz *= beta; lambda = lambda / (yBlockSize * xBlockSize * beta); var iter = 0; while (iter < maxIteration) { bool containsNonZero = false; var maxBlocks = GetMaxBlocks(bMap, xImage2, lipschitz, (float)lambda, (float)alpha, yBlockSize, xBlockSize, theta); foreach (var b in maxBlocks) { var yBlock = b.Item1; var xBlock = b.Item2; var block = RandomBlockCD2.CopyFrom(bMap, yBlock, xBlock, yBlockSize, xBlockSize); var update = block / lipschitz; var xOld = RandomBlockCD2.CopyFrom(xImage2, yBlock, xBlock, yBlockSize, xBlockSize); var optimized = xOld + update; //shrink for (int j = 0; j < optimized.Count; j++) { optimized[j] = CommonDeprecated.ShrinkElasticNet(optimized[j], lambda, alpha); containsNonZero |= (optimized[j] - xOld[j]) != 0.0; } var optDiff = optimized - xOld; RandomBlockCD2.AddInto(xDiff, optDiff, yBlock, xBlock, yBlockSize, xBlockSize); RandomBlockCD2.AddInto(xImage2, optDiff, yBlock, xBlock, yBlockSize, xBlockSize); } if (containsNonZero) { //FitsIO.Write(xImage2, "xImageBlock.fits"); //FitsIO.Write(xDiff, "xDiff.fits"); //update b-map bMapUpdateCalculator.ConvolveInPlace(xDiff); //FitsIO.Write(xDiff, "bMapUpdate.fits"); for (int i = 0; i < xDiff.GetLength(0); i++) { for (int j = 0; j < xDiff.GetLength(1); j++) { bMap[i, j] -= xDiff[i, j]; xDiff[i, j] = 0; } } //FitsIO.Write(bMap, "bMap2.fits"); //calc residuals for debug purposes /*if (maxBlock.Item3 < epsilon) * break;*/ //Console.WriteLine(maxBlock.Item3 + "\t yB = " + yB + "\t xB =" + xB); } iter++; } var elasticNet = 0.0; for (int i = 0; i < xImage.GetLength(0); i++) { for (int j = 0; j < xImage.GetLength(1); j++) { xDiff[i, j] = xImage2[i, j] - (float)xImage[i, j]; xImage[i, j] = xImage2[i, j]; elasticNet += lambda * 2 * lipschitz * GreedyBlockCD.ElasticNetPenalty(xImage2[i, j], (float)alpha); } } resUpdateCalculator.ConvolveInPlace(xDiff); //FitsIO.Write(xDiff, "residualsUpdate.fits"); for (int i = 0; i < xDiff.GetLength(0); i++) { for (int j = 0; j < xDiff.GetLength(1); j++) { residuals[i, j] -= xDiff[i, j]; xDiff[i, j] = 0; } } var l2Penalty = NaiveGreedyCD.CalcDataObjective(residuals); Console.WriteLine("-------------------------"); Console.WriteLine((l2Penalty + elasticNet)); var io = System.IO.File.AppendText("penalty" + yBlockSize + ".txt"); io.WriteLine("l2: " + l2Penalty + "\telastic: " + elasticNet + "\t " + (l2Penalty + elasticNet)); io.Close(); Console.WriteLine("-------------------------"); return(false); }
public static bool Deconvolve(double[,] xImage, double[,] b, double[,] psf, double lambda, double alpha, int maxIteration = 100, double epsilon = 1e-4) { var yPsfHalf = psf.GetLength(0) / 2; var xPsfHalf = psf.GetLength(1) / 2; var aMap = CommonDeprecated.PSF.CalcAMap(xImage, psf); var imageSection = new Common.Rectangle(0, 0, xImage.GetLength(0), xImage.GetLength(1)); //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 psfTmp = new double[psf.GetLength(0) + +psf.GetLength(0), psf.GetLength(1) + psf.GetLength(1)]; for (int y = 0; y < psf.GetLength(0); y++) { for (int x = 0; x < psf.GetLength(1); x++) { psfTmp[y + yPsfHalf + 1, x + xPsfHalf + 1] = psf[psf.GetLength(0) - y - 1, psf.GetLength(1) - x - 1]; } } FFT.Shift(psfTmp); var PsfCorr = FFT.Forward(psfTmp, 1.0); psfTmp = new double[psf.GetLength(0) + psf.GetLength(0), psf.GetLength(1) + psf.GetLength(1)]; CommonDeprecated.PSF.SetPSFInWindow(psfTmp, xImage, psf, xImage.GetLength(0) / 2, xImage.GetLength(1) / 2); var tmp = FFT.Forward(psfTmp, 1.0); var tmp2 = Common.Fourier2D.Multiply(tmp, PsfCorr); //cached bUpdate. When the PSF is not masked var bUpdateCache = FFT.Backward(tmp2, (double)(tmp2.GetLength(0) * tmp2.GetLength(1))); //masked psf var maskedPsf = new double[psf.GetLength(0) + +psf.GetLength(0), psf.GetLength(1) + psf.GetLength(1)]; double[,] bUpdateMasked; int iter = 0; bool converged = false; var watch = new System.Diagnostics.Stopwatch(); watch.Start(); while (!converged & iter < maxIteration) { var yPixel = -1; var xPixel = -1; var xMax = 0.0; var xNew = 0.0; for (int y = 0; y < b.GetLength(0); y++) { for (int x = 0; x < b.GetLength(1); x++) { var yLocal = y; var xLocal = x; var currentA = aMap[y, x]; var old = xImage[yLocal, xLocal]; var xTmp = old + b[y, x] / currentA; xTmp = CommonDeprecated.ShrinkElasticNet(xTmp, lambda, alpha); var xDiff = old - xTmp; if (Math.Abs(xDiff) > xMax) { yPixel = y; xPixel = x; xMax = Math.Abs(xDiff); xNew = xTmp; } } } converged = Math.Abs(xMax) < epsilon; if (!converged) { var yLocal2 = yPixel; var xLocal2 = xPixel; var xOld = xImage[yLocal2, xLocal2]; xImage[yLocal2, xLocal2] = xNew; Console.WriteLine(iter + "\t" + (xNew - xOld) + "\t" + yLocal2 + "\t" + xLocal2); if (yPixel - yPsfHalf >= 0 & yPixel + yPsfHalf < xImage.GetLength(0) & xPixel - xPsfHalf >= 0 & xPixel + xPsfHalf < xImage.GetLength(0)) { UpdateB(b, bUpdateCache, imageSection, yPixel, xPixel, xOld - xNew); } else { /*CommonMethods.PSF.SetPSFInWindow(maskedPsf, xImage, psf, yPixel, xPixel); * tmp = FFT.FFTDebug(maskedPsf, 1.0); * tmp2 = Common.Fourier2D.Multiply(tmp, PsfCorr); * bUpdateMasked = FFT.IFFTDebug(tmp2, tmp2.GetLength(0) * tmp2.GetLength(1)); * UpdateB(b, bUpdateMasked, imageSection, yPixel, xPixel, xOld - xNew);*/ UpdateB(b, bUpdateCache, imageSection, yPixel, xPixel, xOld - xNew); } iter++; if (iter == 1000) { //FitsIO.Write(shrinked, "shrinkedReal.fits"); //FitsIO.Write(b, "candidatesGreedy2.fits"); //FitsIO.Write(xImage, "xImageGreedy2.fits"); } } } watch.Stop(); Console.WriteLine(watch.Elapsed); return(converged); }
public static bool Deconvolve(double[,] xImage, double[,] bMap, double[,] psf, double lambda, double alpha, int maxIteration = 100, double epsilon = 1e-4) { bool converged = false; var aMap = CommonDeprecated.PSF.CalcAMap(xImage, psf); var padding = new Rectangle(0, 0, xImage.GetLength(0), xImage.GetLength(1)); var psfCorrelated = PSF.CalcPaddedFourierCorrelation(ToFloatImage(psf), padding); var psf2 = Common.PSF.CalcPSFSquared(ToFloatImage(psf)); var xDiff = new double[xImage.GetLength(0), xImage.GetLength(1)]; var imageSection = new Common.Rectangle(0, 0, xImage.GetLength(0), xImage.GetLength(1)); var rand = new Random(33); var iter = 0; var theta = 1; //2; //theta, also number of processors. var degreeOfSep = CountNonZero(psf); var blockCount = xImage.Length; var beta = 1.0 + (degreeOfSep - 1) * (theta - 1) / (Math.Max(1.0, (blockCount - 1))); //arises from E.S.O of theta-nice sampling /* * Theta-nice sampling := take theta number of random pixels */ var yPsfHalf = psf.GetLength(0) / 2; var xPsfHalf = psf.GetLength(1) / 2; var psfTmp = new double[psf.GetLength(0) + +psf.GetLength(0), psf.GetLength(1) + psf.GetLength(1)]; for (int y = 0; y < psf.GetLength(0); y++) { for (int x = 0; x < psf.GetLength(1); x++) { psfTmp[y + yPsfHalf + 1, x + xPsfHalf + 1] = psf[psf.GetLength(0) - y - 1, psf.GetLength(1) - x - 1]; } } FFT.Shift(psfTmp); var PsfCorr = FFT.Forward(psfTmp, 1.0); psfTmp = new double[psf.GetLength(0) + psf.GetLength(0), psf.GetLength(1) + psf.GetLength(1)]; CommonDeprecated.PSF.SetPSFInWindow(psfTmp, xImage, psf, xImage.GetLength(0) / 2, xImage.GetLength(1) / 2); var tmp = FFT.Forward(psfTmp, 1.0); var tmp2 = Common.Fourier2D.Multiply(tmp, PsfCorr); var pixelAcces = new double[xImage.GetLength(0), xImage.GetLength(1)]; while (!converged & iter < maxIteration) { // create sampling var samples = CreateSamples(xImage.Length, theta, rand); for (int i = 0; i < samples.Length; i++) { var yPixel = samples[i] / xImage.GetLength(1); var xPixel = samples[i] % xImage.GetLength(1); //update with E.S.O //var xDiffPixel = 2.0 * bMap[y, x] / (beta * aMap[y, x]); //update without E.S.O var xDiffPixel = bMap[yPixel, xPixel] / (aMap[yPixel, xPixel]); var old = xImage[yPixel, xPixel]; var xDiffShrink = CommonDeprecated.ShrinkElasticNet(old + xDiffPixel, lambda, alpha); xDiff[yPixel, xPixel] = xDiffShrink; pixelAcces[yPixel, xPixel] += 1; } //update B-map //reset xDiff for (int i = 0; i < samples.Length; i++) { var yPixel = samples[i] / xImage.GetLength(1); var xPixel = samples[i] % xImage.GetLength(1); var bla = xDiff[yPixel, xPixel]; if (bla != 0.0) { if (yPixel - yPsfHalf >= 0 & yPixel + yPsfHalf < xImage.GetLength(0) & xPixel - xPsfHalf >= 0 & xPixel + xPsfHalf < xImage.GetLength(0)) { UpdateB(bMap, psf2, imageSection, yPixel, xPixel, -xDiff[yPixel, xPixel]); } else { CommonDeprecated.PSF.SetPSFInWindow(psfTmp, xImage, psf, yPixel, xPixel); tmp = FFT.Forward(psfTmp, 1.0); tmp2 = Common.Fourier2D.Multiply(tmp, PsfCorr); var bUpdateMasked = FFT.Backward(tmp2, tmp2.GetLength(0) * tmp2.GetLength(1)); UpdateB(bMap, Common.ToFloatImage(bUpdateMasked), imageSection, yPixel, xPixel, -xDiff[yPixel, xPixel]); } xImage[yPixel, xPixel] += xDiff[yPixel, xPixel]; xDiff[yPixel, xPixel] = 0; Console.WriteLine("iter " + iter + " y " + yPixel + " x " + xPixel + " val " + bla); } Console.WriteLine("iter " + iter); } iter++; } FitsIO.Write(pixelAcces, "pixelAccess.fits"); return(converged); }
public static bool Deconvolve2(double[,] xImage, double[,] residuals, double[,] psf, double lambda, double alpha, int blockSize, int maxIteration = 100, double epsilon = 1e-4) { var xImage2 = ToFloatImage(xImage); var PSFConvolution = CommonDeprecated.PSF.CalcPaddedFourierConvolution(psf, residuals.GetLength(0), residuals.GetLength(1)); var PSFCorrelation = CommonDeprecated.PSF.CalculateFourierCorrelation(psf, residuals.GetLength(0), residuals.GetLength(1)); var PSFSquared = Fourier2D.Multiply(PSFConvolution, PSFCorrelation); var bMapCalculator = new PaddedConvolver(PSFCorrelation, new Rectangle(0, 0, psf.GetLength(0), psf.GetLength(1))); var resUpdateCalculator = new PaddedConvolver(PSFConvolution, new Rectangle(0, 0, psf.GetLength(0), psf.GetLength(1))); var bMapUpdateCalculator = new PaddedConvolver(PSFSquared, new Rectangle(0, 0, psf.GetLength(0), psf.GetLength(1))); var yBlockSize = blockSize; var xBlockSize = blockSize; lambda = lambda / (yBlockSize * xBlockSize); var bMap = ToFloatImage(residuals); bMapCalculator.ConvolveInPlace(bMap); FitsIO.Write(bMap, "bmapFirst.fits"); var xDiff = new float[xImage.GetLength(0), xImage.GetLength(1)]; var lipschitz = ApproximateLipschitz(psf, yBlockSize, xBlockSize); var startL2 = NaiveGreedyCD.CalcDataObjective(residuals); var iter = 0; while (iter < maxIteration) { var maxBlock = GetMaxBlock(bMap, xImage2, lipschitz, (float)lambda, (float)alpha, yBlockSize, xBlockSize); var yB = maxBlock.Item1; var xB = maxBlock.Item2; //yB = 64 / yBlockSize; //xB = 64 / xBlockSize; var block = CopyFrom(bMap, yB, xB, yBlockSize, xBlockSize); //var optimized = block * blockInversion; var update = block / lipschitz; var xOld = CopyFrom(xImage2, yB, xB, yBlockSize, xBlockSize); var optimized = xOld + update; //shrink bool containsNonZero = false; for (int i = 0; i < optimized.Count; i++) { optimized[i] = CommonDeprecated.ShrinkElasticNet(optimized[i], lambda, alpha); containsNonZero |= (optimized[i] - xOld[i]) != 0.0; } var optDiff = optimized - xOld; if (containsNonZero) { AddInto(xDiff, optDiff, yB, xB, yBlockSize, xBlockSize); AddInto(xImage2, optDiff, yB, xB, yBlockSize, xBlockSize); //FitsIO.Write(xImage2, "xImageBlock.fits"); //FitsIO.Write(xDiff, "xDiff.fits"); //update b-map bMapUpdateCalculator.ConvolveInPlace(xDiff); //FitsIO.Write(xDiff, "bMapUpdate.fits"); for (int i = 0; i < xDiff.GetLength(0); i++) { for (int j = 0; j < xDiff.GetLength(1); j++) { bMap[i, j] -= xDiff[i, j]; xDiff[i, j] = 0; } } //FitsIO.Write(bMap, "bMap2.fits"); //calc residuals for debug purposes /*if (maxBlock.Item3 < epsilon) * break;*/ Console.WriteLine(maxBlock.Item3 + "\t yB = " + yB + "\t xB =" + xB); } iter++; } var elasticNet = 0.0; for (int i = 0; i < xImage.GetLength(0); i++) { for (int j = 0; j < xImage.GetLength(1); j++) { xDiff[i, j] = xImage2[i, j] - (float)xImage[i, j]; xImage[i, j] = xImage2[i, j]; elasticNet += lambda * 2 * lipschitz * ElasticNetPenalty(xImage2[i, j], (float)alpha); } } resUpdateCalculator.ConvolveInPlace(xDiff); //FitsIO.Write(xDiff, "residualsUpdate.fits"); for (int i = 0; i < xDiff.GetLength(0); i++) { for (int j = 0; j < xDiff.GetLength(1); j++) { residuals[i, j] -= xDiff[i, j]; xDiff[i, j] = 0; } } var l2Penalty = NaiveGreedyCD.CalcDataObjective(residuals); Console.WriteLine("-------------------------"); Console.WriteLine((l2Penalty + elasticNet)); var io = System.IO.File.AppendText("penalty" + yBlockSize + ".txt"); io.WriteLine("l2: " + l2Penalty + "\telastic: " + elasticNet + "\t " + (l2Penalty + elasticNet)); io.Close(); Console.WriteLine("-------------------------"); return(false); }