예제 #1
0
        void Update()
        {
            ocean.SetFloat(OceanConst.SHADER_TIME, _time += Time.deltaTime * timeScale);
            ocean.SetTexture(OceanConst.KERNEL_UPDATE_H, OceanConst.SHADER_H0_TEX, _h0Tex);
            ocean.SetTexture(OceanConst.KERNEL_UPDATE_H, OceanConst.SHADER_W_TEX, _wTex);
            ocean.SetTexture(OceanConst.KERNEL_UPDATE_H, OceanConst.SHADER_H_TEX, _hTex);
            _hTex.DiscardContents();
            ocean.Dispatch(OceanConst.KERNEL_UPDATE_H, _nGroups, _nGroups, 1);

            var heightTex   = _fft.Backward(_hTex);
            var heightTexDx = 1f / heightTex.width;

            ocean.SetFloat(OceanConst.SHADER_DX, oceanSize * heightTexDx);
            ocean.SetFloat(OceanConst.SHADER_HEIGHT_TEX_DX, heightTexDx);
            ocean.SetFloat(OceanConst.SHADER_HEIGHT, height);
            ocean.SetTexture(OceanConst.KERNEL_UPDATE_N, OceanConst.SHADER_HEIGHT_TEX, heightTex);
            ocean.SetTexture(OceanConst.KERNEL_UPDATE_N, OceanConst.SHADER_N_TEX, _nTex);
            _nTex.DiscardContents();
            ocean.Dispatch(OceanConst.KERNEL_UPDATE_N, _nGroups, _nGroups, 1);

            _block.SetTexture(SHADER_HEIGHT_MAP, heightTex);
            _block.SetTexture(SHADER_NORMAL_MAP, _nTex);
            var viewPos = (Vector4)view.position;

            viewPos.w = 1f;
            _block.SetVector(SHADER_WORLD_VIEW, viewPos);
            _block.SetTexture(SHADER_H0_MAP, _h0Tex);
            _block.SetTexture(SHADER_W_MAP, _wTex);
            _block.SetFloat(SHADER_HEIGHT, height);
            for (var i = 0; i < _renderers.Length; i++)
            {
                _renderers[i].SetPropertyBlock(_block);
            }
        }
예제 #2
0
        public static double[,] ConvolveFFTPaddedInverted(double[,] img, double[,] psf)
        {
            var yHalf = img.GetLength(0) / 2;
            var xHalf = img.GetLength(1) / 2;
            var img2  = new double[img.GetLength(0) * 2, img.GetLength(1) * 2];
            var psf2  = new double[img.GetLength(0) * 2, img.GetLength(1) * 2];

            for (int i = 0; i < img.GetLength(0); i++)
            {
                for (int j = 0; j < img.GetLength(1); j++)
                {
                    img2[i + yHalf, j + xHalf]         = img[i, j];
                    psf2[i + yHalf + 1, j + xHalf + 1] = psf[psf.GetLength(0) - i - 1, psf.GetLength(1) - j - 1];
                }
            }
            var IMG  = FFT.Forward(img2, 1.0);
            var PSF  = FFT.Forward(psf2, 1.0);
            var CONV = Common.Fourier2D.Multiply(IMG, PSF);
            var conv = FFT.Backward(CONV, (double)(img2.GetLength(0) * img2.GetLength(1)));

            FFT.Shift(conv);

            var convOut = new double[img.GetLength(0), img.GetLength(1)];

            for (int i = 0; i < img.GetLength(0); i++)
            {
                for (int j = 0; j < img.GetLength(1); j++)
                {
                    convOut[i, j] = conv[i + yHalf, j + xHalf];
                }
            }

            return(convOut);
        }
예제 #3
0
        public static bool Deconvolve(double[,] xImage, double[,] residuals, double[,] psf, double lambda, double alpha, int maxIteration = 100, double epsilon = 1e-4)
        {
            FitsIO.Write(residuals, "res.fits");
            var yBlockSize = 2;
            var xBlockSize = 2;

            var psfCorrelated    = CommonDeprecated.PSF.CalculateFourierCorrelation(psf, residuals.GetLength(0) - psf.GetLength(0), residuals.GetLength(1) - psf.GetLength(1));
            var residualsFourier = FFT.Forward(residuals);

            residualsFourier = Common.Fourier2D.Multiply(residualsFourier, psfCorrelated);
            var bMap = FFT.Backward(residualsFourier, residualsFourier.Length);

            //FFT.Shift(bMap);
            FitsIO.Write(bMap, "bMap.fits");

            var psf2Fourier = Common.Fourier2D.Multiply(psfCorrelated, psfCorrelated);

            var xDiff          = new double[xImage.GetLength(0), xImage.GetLength(1)];
            var blockInversion = CalcBlockInversion(psf, yBlockSize, xBlockSize);
            var random         = new Random(123);

            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 xOld      = CopyFrom(xImage, yB, xB, yBlockSize, xBlockSize);
                optimized = xOld + optimized;

                //shrink

                /*for (int i = 0; i < optimized.Count; i++)
                 *  optimized[i] = Common.ShrinkElasticNet(optimized[i], lambda, alpha);*/
                var optDiff = optimized - xOld;
                AddInto(xDiff, optDiff, yB, xB, yBlockSize, xBlockSize);
                AddInto(xImage, optDiff, yB, xB, yBlockSize, xBlockSize);
                FitsIO.Write(xImage, "xImageBlock.fits");


                //update b-map
                var XDIFF = FFT.Forward(xDiff);
                XDIFF = Common.Fourier2D.Multiply(XDIFF, psf2Fourier);
                Common.Fourier2D.SubtractInPlace(residualsFourier, XDIFF);
                bMap = FFT.Backward(residualsFourier, residualsFourier.Length);
                FitsIO.Write(bMap, "bMap2.fits");

                //clear from xDiff
                AddInto(xDiff, -optDiff, yB, xB, yBlockSize, xBlockSize);
                iter++;
            }

            return(false);
        }
예제 #4
0
        public static double[,] ConvolveFFT(double[,] img, double[,] psf)
        {
            var IMG  = FFT.Forward(img, 1.0);
            var PSF  = FFT.Forward(psf, 1.0);
            var CONV = Common.Fourier2D.Multiply(IMG, PSF);
            var conv = FFT.Backward(CONV, (double)(img.GetLength(0) * img.GetLength(1)));

            FFT.Shift(conv);
            return(conv);
        }
        public static double[,] ToImage(GriddingConstants c, List <List <Subgrid> > metadata, Complex[,,] visibilities, double[,,] uvw, double[] frequencies)
        {
            var gridded   = Gridder.Forward(c, metadata, uvw, visibilities, frequencies, c.SubgridSpheroidal);
            var ftgridded = SubgridFFT.Forward(c, gridded);
            var grid      = Adder.Add(c, metadata, ftgridded);

            FFT.Shift(grid);
            var img = FFT.Backward(grid, c.VisibilitiesCount);

            FFT.Shift(img);

            //remove spheroidal from grid

            /*for (int y = 0; y < img.GetLength(0); y++)
             *  for (int x = 0; x < img.GetLength(1); x++)
             *      img[y, x] = img[y, x] / c.GridSpheroidal[y, x];*/

            return(img);
        }
        public static double[,] CalculatePSF(GriddingConstants c, List <List <Subgrid> > metadata, double[,,] uvw, bool[,,] flags, double[] frequencies)
        {
            var visibilities = new Complex[uvw.GetLength(0), uvw.GetLength(1), frequencies.Length];

            for (int i = 0; i < visibilities.GetLength(0); i++)
            {
                for (int j = 0; j < visibilities.GetLength(1); j++)
                {
                    for (int k = 0; k < visibilities.GetLength(2); k++)
                    {
                        if (!flags[i, j, k])
                        {
                            visibilities[i, j, k] = new Complex(1.0, 0);
                        }
                        else
                        {
                            visibilities[i, j, k] = new Complex(0, 0);
                        }
                    }
                }
            }


            var gridded   = Gridder.Forward(c, metadata, uvw, visibilities, frequencies, c.SubgridSpheroidal);
            var ftgridded = SubgridFFT.Forward(c, gridded);
            var grid      = Adder.Add(c, metadata, ftgridded);

            FFT.Shift(grid);
            var psf = FFT.Backward(grid, c.VisibilitiesCount);

            FFT.Shift(psf);

            //remove spheroidal from grid

            /*for (int y = 0; y < psf.GetLength(0); y++)
             *  for (int x = 0; x < psf.GetLength(1); x++)
             *      psf[y, x] = psf[y, x] / c.GridSpheroidal[y, x];*/

            return(psf);
        }
예제 #7
0
        public static bool Deconvolve(double[,] xImage, double[,] residuals, double[,] psf, double lambda, double alpha, int maxIteration = 100, double epsilon = 1e-4)
        {
            FitsIO.Write(residuals, "res.fits");
            var yBlockSize = 2;
            var xBlockSize = 2;

            var PSFCorrelated = CommonDeprecated.PSF.CalculateFourierCorrelation(psf, psf.GetLength(0), psf.GetLength(1));
            var RES           = FFT.Forward(residuals);
            var BMAPFourier   = Common.Fourier2D.Multiply(RES, PSFCorrelated);
            var bMap          = FFT.Backward(BMAPFourier, BMAPFourier.Length);

            //FFT.Shift(bMap);
            FitsIO.Write(bMap, "bMap.fits");
            var PSF = FFT.Forward(CommonDeprecated.Residuals.Pad(psf, psf.GetLength(0), psf.GetLength(1)), 1.0);

            var PSF2Fourier = Common.Fourier2D.Multiply(PSF, PSFCorrelated);

            var xDiff = new double[xImage.GetLength(0), xImage.GetLength(1)];
            //var blockInversion = CalcBlock(psf, yBlockSize, xBlockSize).Inverse();
            var random = new Random(123);

            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 optimized = block / lipschitz /4;
                 * var xOld = CopyFrom(xImage, yB, xB, yBlockSize, xBlockSize);
                 * optimized = xOld + optimized;
                 *
                 * //shrink
                 * for (int i = 0; i < optimized.Count; i++)
                 *  optimized[i] = Common.ShrinkElasticNet(optimized[i], lambda, alpha);
                 * var optDiff = optimized - xOld;
                 * //AddInto(xDiff, optDiff, yB, xB, yBlockSize, xBlockSize);
                 * AddInto(xImage, optDiff, yB, xB, yBlockSize, xBlockSize);
                 * FitsIO.Write(xImage, "xImageBlock.fits");
                 * FitsIO.Write(xDiff, "xDiff.fits");
                 * xDiff[64, 64] = 1.0;
                 *
                 * //update b-map
                 * var XDIFF = FFT.Forward(xDiff);
                 * XDIFF = Common.Fourier2D.Multiply(XDIFF, PSF2Fourier);
                 * Common.Fourier2D.SubtractInPlace(BMAPFourier, XDIFF);
                 * bMap = FFT.Backward(BMAPFourier, BMAPFourier.Length);
                 * //FFT.Shift(bMap);
                 * FitsIO.Write(bMap, "bMap2.fits");
                 *
                 * //calc residuals for debug purposes
                 * var XDIFF2 = FFT.Forward(xDiff);
                 * XDIFF2 = Common.Fourier2D.Multiply(XDIFF2, PSF);
                 * var RES2 = Common.Fourier2D.Subtract(RES, XDIFF2);
                 * var resDebug = FFT.Backward(RES2, RES2.Length);
                 * var L2 = NaiveGreedyCD.CalcDataObjective(resDebug);
                 * FitsIO.Write(resDebug, "resDebug.fits");
                 * var xDiff3 = FFT.Backward(XDIFF2, XDIFF2.Length);
                 * FitsIO.Write(xDiff3, "recDebug.fits");
                 *
                 * //clear from xDiff
                 * AddInto(xDiff, -optDiff, yB, xB, yBlockSize, xBlockSize);*/
                iter++;
            }

            return(false);
        }
예제 #8
0
        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);
        }
예제 #9
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);
        }
예제 #10
0
        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 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 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);
        }
예제 #13
0
        public static void RunToy()
        {
            var psf = new double[32, 32];

            for (int i = 15; i < 18; i++)
            {
                for (int j = 15; j < 18; j++)
                {
                    psf[i, j] = 0.5;
                }
            }
            psf[16, 16] = 1.0;
            //psf[17, 17] = 0.8;

            var AA = CalcAgain(psf);

            var yBSize   = 2;
            var xBSize   = 2;
            var blockInv = CalcBlockInversion(psf, 2, 2);
            var inv      = AA.Inverse();

            Console.WriteLine(blockInv);
            Console.WriteLine(inv);

            var xImage      = new double[32, 32];
            var groundTruth = new double[32, 32];

            groundTruth[16, 16] = 1.0;
            //dirty[16, 17] = 1.8;
            //dirty[17, 16] = 1.1;
            //dirty[17, 17] = 0.5;
            //dirty[16, 20] = 0.5;
            var IMG       = FFT.Forward(groundTruth, 1.0);
            var PSF       = FFT.Forward(psf, 1.0);
            var CONV      = Common.Fourier2D.Multiply(IMG, PSF);
            var residuals = FFT.Backward(CONV, (double)(IMG.GetLength(0) * IMG.GetLength(1)));

            FFT.Shift(residuals);

            var RES = FFT.Forward(residuals, 1.0);
            //TODO: WRONG WRONG WRONG, its PSFCorrelated. But does not matter for toy PSF
            var BMAP = Common.Fourier2D.Multiply(RES, PSF);
            var bMap = FFT.Backward(BMAP, (double)(BMAP.GetLength(0) * BMAP.GetLength(1)));

            FFT.Shift(bMap);

            FitsIO.Write(bMap, "bMapToy.fits");
            Console.WriteLine(AA.Inverse());

            var bVec = CopyFrom(bMap, 16 / yBSize, 16 / xBSize, yBSize, xBSize);

            var res3  = (inv * bVec);
            var array = res3.ToArray();

            Deconvolve(xImage, residuals, psf, 0.0, 1.0, 1);

            /*
             * AddInto(xImage, res3, 16 / yBSize, 16 / xBSize, yBSize, xBSize);
             * var XIMG = FFT.Forward(xImage, 1.0);
             * var RESCONV = Common.Fourier2D.Multiply(XIMG, PSF);
             * var results = FFT.Backward(RESCONV, (double)(BMAP.GetLength(0) * BMAP.GetLength(1)));
             * FFT.Shift(results);
             * FitsIO.Write(results, "dirtyConf.fits");
             * FitsIO.Write(xImage, "dXXConf.fits");*/
        }
        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);
        }
예제 #15
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);
        }