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);
        }
Beispiel #2
0
        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));
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        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);
        }
Beispiel #7
0
        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);
        }
Beispiel #8
0
        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);
        }