public static float[,] CalcGradientMap(float[,] residuals, Complex[,] psfCorrelation, Rectangle psfSize) { var yPadding = psfSize.YEnd; var xPadding = psfSize.XEnd; var resPadded = Pad(residuals, yPadding, xPadding); var ResPAdded = FFT.Forward(resPadded, 1.0); var B = Fourier2D.Multiply(ResPAdded, psfCorrelation); var bPadded = FFT.BackwardFloat(B, (double)(B.GetLength(0) * B.GetLength(1))); var bMap = RemovePadding(bPadded, yPadding, xPadding); return(bMap); }
/// <summary> /// Correlate the PSF with itself, and calculate psf squared /// </summary> /// <param name="psf"></param> /// <returns></returns> public static float[,] CalcPSFSquared(float[,] psf) { var psfCorrelated = CalcPaddedFourierCorrelation(psf, new Rectangle(0, 0, psf.GetLength(0), psf.GetLength(1))); var psfPadded = new float[psf.GetLength(0) * 2, psf.GetLength(1) * 2]; var fullWindow = new Rectangle(0, 0, psfPadded.GetLength(0), psfPadded.GetLength(1)); SetPsfInWindow(psfPadded, psf, fullWindow, psf.GetLength(0), psf.GetLength(1)); var PSF = FFT.Forward(psfPadded); //convolve psf with its flipped version == correlation var PSF2 = Fourier2D.Multiply(PSF, psfCorrelated); var psf2 = FFT.Backward(PSF2, psfCorrelated.Length); return(ToFloatImage(psf2)); }
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[,] 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 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); }