private Pixel GetAbsMax(float[,] xImage, float[,] bMap, float lambda, float alpha) { var currentMax = new Pixel(0, -1, -1); for (int y = 0; y < imageSection.YExtent(); y++) { for (int x = 0; x < imageSection.XExtent(); x++) { var currentA = aMap[y, x]; var old = xImage[y, x]; var xTmp = ElasticNet.ProximalOperator(old * currentA + bMap[y, x], currentA, lambda, alpha); var xDiff = xTmp - old; if (currentMax.MaxDiff < Math.Abs(xDiff)) { var yGlobal = y + imageSection.Y; var xGlobal = x + imageSection.X; currentMax = new Pixel(xDiff, yGlobal, xGlobal); } } } var maxPixelGlobal = comm.Allreduce(currentMax, (aC, bC) => aC.MaxDiff > bC.MaxDiff ? aC : bC); return(maxPixelGlobal); }
public static Tuple <int, int, double>[] GetMaxBlocks(float[,] gExplore, float[,] gCorrection, float[,] xExplore, float stepSize, float theta, float lambda, float alpha, int yBlockSize, int xBlockSize, int tau) { var yBlocks = gExplore.GetLength(0) / yBlockSize; var xBlocks = gExplore.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 update = theta * gCorrection[y, x] + gExplore[y, x] + xExplore[y, x] * stepSize; var shrink = ElasticNet.ProximalOperator(update, stepSize, lambda, alpha) - xExplore[y, x]; sum += Math.Abs(shrink); } } 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> [tau]; for (int i = 0; i < tau; i++) { output[i] = tmp[tmp.Count - i - 1]; } return(output); }
public void Deconvolve() { var update = 0.0f; var blockCount = shared.XExpl.Length; float eta = 1.0f / blockCount; DiffMax = 0.0f; var beta = CalcESO(shared.ProcessorCount, shared.DegreeOfSeperability, blockCount); var continueAsync = Thread.VolatileRead(ref shared.AsyncFinished) == 0; for (int inner = 0; inner < shared.MaxConcurrentIterations & continueAsync; inner++) { continueAsync = Thread.VolatileRead(ref shared.AsyncFinished) == 0; var stepFactor = (float)beta * Theta / shared.Theta0; var theta2 = Theta * Theta; var blockIdx = GetPseudoRandomBlock(stepFactor, theta2); var blockSample = shared.ActiveSet[blockIdx]; var yPixel = blockSample.Item1; var xPixel = blockSample.Item2; var step = shared.AMap[yPixel, xPixel] * stepFactor; var correctionFactor = -(1.0f - Theta / shared.Theta0) / theta2; var xExpl = Thread.VolatileRead(ref shared.XExpl[yPixel, xPixel]); update = theta2 * Thread.VolatileRead(ref shared.GCorr[yPixel, xPixel]) + Thread.VolatileRead(ref shared.GExpl[yPixel, xPixel]) + xExpl * step; update = ElasticNet.ProximalOperator(update, step, shared.Lambda, shared.Alpha) - xExpl; DiffMax = Math.Max(DiffMax, Math.Abs(update)); //update gradients if (0.0f != Math.Abs(update)) { UpdateGradientsApprox(shared.GExpl, shared.GCorr, shared.Psf2, updateCache, yPixel, xPixel, correctionFactor, update); var oldExplore = shared.XExpl[yPixel, xPixel]; //does not need to be volatile, this index is blocked until this process is finished, and we already made sure with a volatile read that the latest value is in the cache var oldXCorr = Thread.VolatileRead(ref shared.XCorr[yPixel, xPixel]); var newXExplore = oldExplore + update; Thread.VolatileWrite(ref shared.XExpl[yPixel, xPixel], shared.XExpl[yPixel, xPixel] + update); Thread.VolatileWrite(ref shared.XCorr[yPixel, xPixel], shared.XCorr[yPixel, xPixel] + update * correctionFactor); //not 100% sure this is the correct generalization from single pixel thread rule to block rule var testRestartUpdate = (update) * (newXExplore - (theta2 * oldXCorr + oldExplore)); ConcurrentUpdateTestRestart(ref shared.TestRestart, eta, testRestartUpdate); } AsyncIterations++; //unlockBlock Thread.VolatileWrite(ref shared.BlockLock[blockIdx], 0); Theta = (float)(Math.Sqrt((theta2 * theta2) + 4 * (theta2)) - theta2) / 2.0f; } Thread.VolatileWrite(ref shared.AsyncFinished, 1); }
private static float GetMaxAbsPixelValue(SharedData shared, Tuple <int, int> block, float stepFactor) { var yPixel = block.Item1; var xPixel = block.Item2; var step = shared.AMap[yPixel, xPixel] * stepFactor; var xExpl = Thread.VolatileRead(ref shared.XExpl[yPixel, xPixel]); var update = Thread.VolatileRead(ref shared.GExpl[yPixel, xPixel]) + xExpl * step; update = ElasticNet.ProximalOperator(update, step, shared.Lambda, shared.Alpha) - xExpl; return(Math.Abs(update)); }
public static Tuple <double, double> EstimateObjectives(float[,] xImage, float[,] residuals, float[,] psf, float[,] xExplore, float[,] xAccelerated, float lambda, float alpha, float[,] psfCut, float[,] bMap) { Tuple <double, double> output = null; var CONVKernel = PSF.CalcPaddedFourierConvolution(psf, new Rectangle(0, 0, residuals.GetLength(0), residuals.GetLength(1))); using (var residualsCalculator = new PaddedConvolver(CONVKernel, new Rectangle(0, 0, psf.GetLength(0), psf.GetLength(1)))) { var residualsExplore = new float[xImage.GetLength(0), xImage.GetLength(1)]; var residualsAccelerated = new float[xImage.GetLength(0), xImage.GetLength(1)]; for (int i = 0; i < xImage.GetLength(0); i++) { for (int j = 0; j < xImage.GetLength(1); j++) { residualsExplore[i, j] = xExplore[i, j] - xImage[i, j]; residualsAccelerated[i, j] = xAccelerated[i, j] - xImage[i, j]; } } residualsCalculator.ConvolveInPlace(residualsExplore); residualsCalculator.ConvolveInPlace(residualsAccelerated); for (int i = 0; i < xImage.GetLength(0); i++) { for (int j = 0; j < xImage.GetLength(1); j++) { residualsExplore[i, j] = residuals[i, j] - residualsExplore[i, j]; residualsAccelerated[i, j] = residuals[i, j] - residualsAccelerated[i, j]; } } var objectiveExplore = Residuals.CalcPenalty(residualsExplore) + ElasticNet.CalcPenalty(xExplore, lambda, alpha); var objectiveAccelerated = Residuals.CalcPenalty(residualsAccelerated) + ElasticNet.CalcPenalty(xAccelerated, lambda, alpha); /* * var CORRKernel = PSF.CalcPaddedFourierCorrelation(psfCut, new Rectangle(0, 0, residuals.GetLength(0), residuals.GetLength(1))); * var bMapFull = Residuals.CalcBMap(residualsExplore, CORRKernel, new Rectangle(0, 0, psfCut.GetLength(0), psfCut.GetLength(1))); * FitsIO.Write(bMap, "bMapOriginal.fits"); * FitsIO.Write(bMapFull, "bMapSanity.fits"); * var diff = new float[bMap.GetLength(0), bMap.GetLength(1)]; * for (int i = 0; i < xImage.GetLength(0); i++) * for (int j = 0; j < xImage.GetLength(1); j++) * diff[i, j] = bMap[i, j] - bMapFull[i, j]; * FitsIO.Write(diff, "bmapSanityDiff.fits");*/ output = new Tuple <double, double>(objectiveExplore, objectiveAccelerated); } return(output); }
private static List <Tuple <int, int> > GetActiveSet(float[,] xExplore, float[,] gExplore, float lambda, float alpha, float[,] lipschitzMap) { var output = new List <Tuple <int, int> >(); for (int y = 0; y < xExplore.GetLength(0); y++) { for (int x = 0; x < xExplore.GetLength(1); x++) { var lipschitz = lipschitzMap[y, x]; var tmp = gExplore[y, x] + xExplore[y, x] * lipschitz; tmp = ElasticNet.ProximalOperator(tmp, lipschitz, lambda, alpha); if (0.0f < Math.Abs(tmp - xExplore[y, x])) { output.Add(new Tuple <int, int>(y, x)); } } } return(output); }
public static List <Tuple <int, int> > GetActiveSet(float[,] xExplore, float[,] gExplore, int yBlockSize, int xBlockSize, float lambda, float alpha, float[,] lipschitzMap) { var debug = new float[xExplore.GetLength(0), xExplore.GetLength(1)]; var output = new List <Tuple <int, int> >(); for (int i = 0; i < xExplore.GetLength(0) / yBlockSize; i++) { for (int j = 0; j < xExplore.GetLength(1) / xBlockSize; j++) { var yPixel = i * yBlockSize; var xPixel = j * xBlockSize; var nonZero = false; for (int y = yPixel; y < yPixel + yBlockSize; y++) { for (int x = xPixel; x < xPixel + xBlockSize; x++) { var lipschitz = lipschitzMap[y, x]; var tmp = gExplore[y, x] + xExplore[y, x] * lipschitz; tmp = ElasticNet.ProximalOperator(tmp, lipschitz, lambda, alpha); if (0.0f < Math.Abs(tmp - xExplore[y, x])) { nonZero = true; } } } if (nonZero) { output.Add(new Tuple <int, int>(i, j)); for (int y = yPixel; y < yPixel + yBlockSize; y++) { for (int x = xPixel; x < xPixel + xBlockSize; x++) { debug[y, x] = 1.0f; } } } } } FitsIO.Write(debug, "activeSet.fits"); return(output); }
private Pixel GetAbsMaxSingle(Rectangle subpatch, float[,] xImage, float[,] gradients, float lambda, float alpha) { var maxPixels = new Pixel[subpatch.YExtent()]; for (int y = subpatch.Y; y < subpatch.YEnd; y++) { var yLocal = y; var currentMax = new Pixel(-1, -1, 0, 0); for (int x = subpatch.X; x < subpatch.XEnd; x++) { var xLocal = x; var currentA = aMap[yLocal, xLocal]; var old = xImage[yLocal, xLocal]; //var xTmp = old + bMap[y, x] / currentA; //xTmp = ShrinkElasticNet(xTmp, lambda, alpha); var xTmp = ElasticNet.ProximalOperator(old * currentA + gradients[y, x], currentA, lambda, alpha); var xDiff = old - xTmp; if (currentMax.PixelMaxDiff < Math.Abs(xDiff)) { currentMax.Y = y; currentMax.X = x; currentMax.PixelMaxDiff = Math.Abs(xDiff); currentMax.PixelNew = xTmp; } } maxPixels[yLocal] = currentMax; } var maxPixel = new Pixel(-1, -1, 0, 0); for (int i = 0; i < maxPixels.Length; i++) { if (maxPixel.PixelMaxDiff < maxPixels[i].PixelMaxDiff) { maxPixel = maxPixels[i]; } } return(maxPixel); }
private List <Tuple <int, int> > GetActiveSet(float[,] xExplore, float[,] gExplore, float lambda, float alpha, float lipschitz) { var debug = new float[xExplore.GetLength(0), xExplore.GetLength(1)]; var output = new List <Tuple <int, int> >(); for (int i = 0; i < xExplore.GetLength(0) / yBlockSize; i++) { for (int j = 0; j < xExplore.GetLength(1) / xBlockSize; j++) { var yPixel = i * yBlockSize; var xPixel = j * xBlockSize; var nonZero = false; for (int y = yPixel; y < yPixel + yBlockSize; y++) { for (int x = xPixel; x < xPixel + xBlockSize; x++) { var tmp = gExplore[y, x] + xExplore[y, x] * lipschitz; tmp = ElasticNet.ProximalOperator(tmp, lipschitz, lambda, alpha); if (ACTIVE_SET_CUTOFF < Math.Abs(tmp - xExplore[y, x])) { nonZero = true; } } } if (nonZero) { output.Add(new Tuple <int, int>(i, j)); for (int y = yPixel; y < yPixel + yBlockSize; y++) { for (int x = xPixel; x < xPixel + xBlockSize; x++) { debug[y, x] = 1.0f; } } } } } //FitsIO.Write(debug, "activeSet.fits"); //can write max change for convergence purposes return(output); }
public void ISTAStep(float[,] xImage, float[,] residuals, float[,] psf, float lambda, float alpha) { var xOld = Copy(xImage); var corrKernel = PSF.CalcPaddedFourierCorrelation(psf, new Rectangle(0, 0, residuals.GetLength(0), residuals.GetLength(1))); var gradients = Residuals.CalcGradientMap(residuals, corrKernel, new Rectangle(0, 0, psf.GetLength(0), psf.GetLength(1))); var lipschitz = (float)PSF.CalcMaxLipschitz(psf) * xImage.Length; for (int i = 0; i < xImage.GetLength(0); i++) { for (int j = 0; j < xImage.GetLength(1); j++) { var tmp = gradients[i, j] + xImage[i, j] * lipschitz; tmp = ElasticNet.ProximalOperator(tmp, lipschitz, lambda, alpha); xImage[i, j] = tmp; } } //update residuals for (int i = 0; i < xImage.GetLength(0); i++) { for (int j = 0; j < xImage.GetLength(1); j++) { xOld[i, j] = xImage[i, j] - xOld[i, j]; } } var convKernel = PSF.CalcPaddedFourierConvolution(psf, new Rectangle(0, 0, residuals.GetLength(0), residuals.GetLength(1))); var residualsCalculator = new PaddedConvolver(convKernel, new Rectangle(0, 0, psf.GetLength(0), psf.GetLength(1))); residualsCalculator.ConvolveInPlace(xOld); for (int i = 0; i < xImage.GetLength(0); i++) { for (int j = 0; j < xImage.GetLength(1); j++) { residuals[i, j] -= xOld[i, j]; } } }
public static float GetAbsMax(float[,] xImage, float[,] bMap, float[,] aMap, float lambda, float alpha) { var maxPixels = new float[xImage.GetLength(0)]; Parallel.For(0, xImage.GetLength(0), (y) => { var yLocal = y; var currentMax = 0.0f; for (int x = 0; x < xImage.GetLength(1); x++) { var xLocal = x; var currentA = aMap[yLocal, xLocal]; var old = xImage[yLocal, xLocal]; //var xTmp = old + bMap[y, x] / currentA; //xTmp = ShrinkElasticNet(xTmp, lambda, alpha); var xTmp = ElasticNet.ProximalOperator(old * currentA + bMap[y, x], currentA, lambda, alpha); var xDiff = old - xTmp; if (currentMax < Math.Abs(xDiff)) { currentMax = Math.Abs(xDiff); } } maxPixels[yLocal] = currentMax; }); var maxPixel = 0.0f; for (int i = 0; i < maxPixels.Length; i++) { if (maxPixel < maxPixels[i]) { maxPixel = maxPixels[i]; } } return(maxPixel); }
private static float GetMaxAbsBlockValue(SharedData shared, Tuple <int, int> block, float stepFactor, float theta2) { var yOffset = block.Item1 * shared.YBlockSize; var xOffset = block.Item2 * shared.XBlockSize; var blockLipschitz = GetBlockLipschitz(shared.AMap, yOffset, xOffset, shared.YBlockSize, shared.XBlockSize); var step = blockLipschitz * stepFactor; var updateAbsSum = 0.0f; for (int y = yOffset; y < (yOffset + shared.YBlockSize); y++) { for (int x = xOffset; x < (xOffset + shared.XBlockSize); x++) { var xExpl = Thread.VolatileRead(ref shared.XExpl[y, x]); var update = theta2 * Thread.VolatileRead(ref shared.GCorr[y, x]) + Thread.VolatileRead(ref shared.GExpl[y, x]) + xExpl * step; update = ElasticNet.ProximalOperator(update, step, shared.Lambda, shared.Alpha) - xExpl; updateAbsSum += Math.Abs(update); } } return(updateAbsSum); }
private static Tuple <double, double> CalcObjectives(float[,] xImage, float[,] residuals, float[,] psf, float[,] xExplore, float[,] xAccelerated, float lambda, float alpha) { Tuple <double, double> output = null; var CONVKernel = PSF.CalcPaddedFourierConvolution(psf, new Rectangle(0, 0, residuals.GetLength(0), residuals.GetLength(1))); using (var residualsCalculator = new PaddedConvolver(CONVKernel, new Rectangle(0, 0, psf.GetLength(0), psf.GetLength(1)))) { var residualsExplore = new float[xImage.GetLength(0), xImage.GetLength(1)]; var residualsAccelerated = new float[xImage.GetLength(0), xImage.GetLength(1)]; for (int i = 0; i < xImage.GetLength(0); i++) { for (int j = 0; j < xImage.GetLength(1); j++) { residualsExplore[i, j] = xExplore[i, j] - xImage[i, j]; residualsAccelerated[i, j] = xAccelerated[i, j] - xImage[i, j]; } } residualsCalculator.ConvolveInPlace(residualsExplore); residualsCalculator.ConvolveInPlace(residualsAccelerated); for (int i = 0; i < xImage.GetLength(0); i++) { for (int j = 0; j < xImage.GetLength(1); j++) { residualsExplore[i, j] -= residuals[i, j]; residualsAccelerated[i, j] -= residuals[i, j]; } } var objectiveExplore = Residuals.CalcPenalty(residualsExplore) + ElasticNet.CalcPenalty(xExplore, lambda, alpha); var objectiveAccelerated = Residuals.CalcPenalty(residualsAccelerated) + ElasticNet.CalcPenalty(xAccelerated, lambda, alpha); output = new Tuple <double, double>(objectiveExplore, objectiveAccelerated); } return(output); }
public void Deconvolve() { var update = 0.0f; var blockCount = shared.XExpl.Length; DiffMax = 0.0f; var beta = CalcESO(shared.ProcessorCount, shared.DegreeOfSeperability, blockCount); var continueAsync = Thread.VolatileRead(ref shared.AsyncFinished) == 0; for (int inner = 0; inner < shared.MaxConcurrentIterations & continueAsync; inner++) { continueAsync = Thread.VolatileRead(ref shared.AsyncFinished) == 0; var blockIdx = GetPseudoRandomBlock((float)beta); var blockSample = shared.ActiveSet[blockIdx]; var yPixel = blockSample.Item1; var xPixel = blockSample.Item2; var step = shared.AMap[yPixel, xPixel] * (float)beta; var xExpl = Thread.VolatileRead(ref shared.XExpl[yPixel, xPixel]); update = Thread.VolatileRead(ref shared.GExpl[yPixel, xPixel]) + xExpl * step; update = ElasticNet.ProximalOperator(update, step, shared.Lambda, shared.Alpha) - xExpl; DiffMax = Math.Max(DiffMax, Math.Abs(update)); //update gradients if (0.0f != Math.Abs(update)) { UpdateGradients(shared.GExpl, shared.Psf2, yPixel, xPixel, update); Thread.VolatileWrite(ref shared.XExpl[yPixel, xPixel], shared.XExpl[yPixel, xPixel] + update); } AsyncIterations++; //unlockBlock Thread.VolatileWrite(ref shared.BlockLock[blockIdx], 0); } Thread.VolatileWrite(ref shared.AsyncFinished, 1); }
private static void ReconstructSerial(MeasurementData input, GriddingConstants c, float[,] fullPsf, string folder, string file, int processorCount) { var totalWatch = new Stopwatch(); var currentWatch = new Stopwatch(); var totalSize = new Rectangle(0, 0, c.GridSize, c.GridSize); var psfCut = PSF.Cut(fullPsf, CUT_FACTOR_SERIAL); var maxSidelobe = PSF.CalcMaxSidelobe(fullPsf, CUT_FACTOR_SERIAL); var fastCD = new FastSerialCD(totalSize, psfCut, processorCount); var metadata = Partitioner.CreatePartition(c, input.UVW, input.Frequencies); var writer = new StreamWriter(folder + "/" + file + ".txt"); var psfBMap = psfCut; using (var bMapCalculator = new PaddedConvolver(PSF.CalcPaddedFourierCorrelation(psfBMap, totalSize), new Rectangle(0, 0, psfBMap.GetLength(0), psfBMap.GetLength(1)))) using (var bMapCalculator2 = new PaddedConvolver(PSF.CalcPaddedFourierCorrelation(fullPsf, totalSize), new Rectangle(0, 0, fullPsf.GetLength(0), fullPsf.GetLength(1)))) { var currentBMapCalculator = bMapCalculator; var maxLipschitz = PSF.CalcMaxLipschitz(psfCut); var lambda = (float)(LAMBDA * maxLipschitz); var lambdaTrue = (float)(LAMBDA * PSF.CalcMaxLipschitz(fullPsf)); var alpha = ALPHA; var switchedToOtherPsf = false; var xImage = new float[c.GridSize, c.GridSize]; var residualVis = input.Visibilities; DeconvolutionResult lastResult = null; for (int cycle = 0; cycle < 6; cycle++) { Console.WriteLine("cycle " + cycle); var dirtyGrid = IDG.GridW(c, metadata, residualVis, input.UVW, input.Frequencies); var dirtyImage = FFT.WStackIFFTFloat(dirtyGrid, c.VisibilitiesCount); FFT.Shift(dirtyImage); FitsIO.Write(dirtyImage, folder + "/dirty" + cycle + ".fits"); currentWatch.Restart(); totalWatch.Start(); var maxDirty = Residuals.GetMax(dirtyImage); var bMap = bMapCalculator.Convolve(dirtyImage); var maxB = Residuals.GetMax(bMap); var correctionFactor = Math.Max(maxB / (maxDirty * fastCD.MaxLipschitz), 1.0f); var currentSideLobe = maxB * maxSidelobe * correctionFactor; var currentLambda = Math.Max(currentSideLobe / alpha, lambda); var objective = Residuals.CalcPenalty(dirtyImage) + ElasticNet.CalcPenalty(xImage, lambdaTrue, alpha); var absMax = fastCD.GetAbsMaxDiff(xImage, bMap, lambdaTrue, alpha); if (absMax >= MAJOR_STOP) { lastResult = fastCD.Deconvolve(xImage, bMap, currentLambda, alpha, 30000, 1e-5f); } if (lambda == currentLambda & !switchedToOtherPsf) { currentBMapCalculator = bMapCalculator2; lambda = lambdaTrue; switchedToOtherPsf = true; } currentWatch.Stop(); totalWatch.Stop(); writer.WriteLine(cycle + ";" + currentLambda + ";" + objective + ";" + absMax + ";" + lastResult.IterationCount + ";" + totalWatch.Elapsed.TotalSeconds + ";" + currentWatch.Elapsed.TotalSeconds); writer.Flush(); if (absMax < MAJOR_STOP) { break; } FFT.Shift(xImage); var xGrid = FFT.Forward(xImage); FFT.Shift(xImage); var modelVis = IDG.DeGridW(c, metadata, xGrid, input.UVW, input.Frequencies); residualVis = Visibilities.Substract(input.Visibilities, modelVis, input.Flags); } } }
public void Deconvolve() { var blockCount = shared.XExpl.Length / (shared.YBlockSize * shared.XBlockSize); //var blockCount = shared.ActiveSet.Count; float eta = 1.0f / blockCount; var beta = CalcESO(shared.ProcessorCount, shared.DegreeOfSeperability, blockCount); xDiffMax = 0.0f; var continueAsync = Thread.VolatileRead(ref shared.asyncFinished) == 0; for (int inner = 0; inner < shared.MaxConcurrentIterations & continueAsync; inner++) { continueAsync = Thread.VolatileRead(ref shared.asyncFinished) == 0; var blockIdx = GetRandomBlockIdx(random, id, shared.BlockLock); var blockSample = shared.ActiveSet[blockIdx]; var yOffset = blockSample.Item1 * shared.YBlockSize; var xOffset = blockSample.Item2 * shared.XBlockSize; var blockLipschitz = GetBlockLipschitz(shared.AMap, yOffset, xOffset, shared.YBlockSize, shared.XBlockSize); var step = blockLipschitz * (float)beta * Theta / shared.theta0; var theta2 = Theta * Theta; var correctionFactor = -(1.0f - Theta / shared.theta0) / theta2; var updateSum = 0.0f; var updateAbsSum = 0.0f; for (int y = yOffset; y < (yOffset + shared.YBlockSize); y++) { for (int x = xOffset; x < (xOffset + shared.XBlockSize); x++) { var xExpl = Thread.VolatileRead(ref shared.XExpl[y, x]); var update = theta2 * Thread.VolatileRead(ref shared.GCorr[y, x]) + Thread.VolatileRead(ref shared.GExpl[y, x]) + xExpl * step; update = ElasticNet.ProximalOperator(update, step, shared.Lambda, shared.Alpha) - xExpl; blockUpdate[y - yOffset, x - xOffset] = update; updateSum = update; updateAbsSum += Math.Abs(update); } } //update gradients if (0.0f != updateAbsSum) { xDiffMax = Math.Max(xDiffMax, updateAbsSum); UpdateBMaps(blockUpdate, blockSample.Item1, blockSample.Item2, shared.Psf2, shared.GExpl, shared.GCorr, correctionFactor); var newXExplore = 0.0f; var oldXExplore = 0.0f; var oldXCorr = 0.0f; for (int y = yOffset; y < (yOffset + shared.YBlockSize); y++) { for (int x = xOffset; x < (xOffset + shared.XBlockSize); x++) { var update = blockUpdate[y - yOffset, x - xOffset]; var oldExplore = shared.XExpl[y, x]; //does not need to be volatile, this index is blocked until this process is finished, and we already made sure with a volatile read that the latest value is in the cache oldXExplore += shared.XExpl[y, x]; oldXCorr += Thread.VolatileRead(ref shared.XCorr[y, x]); newXExplore += oldExplore + update; Thread.VolatileWrite(ref shared.XExpl[y, x], shared.XExpl[y, x] + update); Thread.VolatileWrite(ref shared.XCorr[y, x], shared.XCorr[y, x] + update * correctionFactor); } } //not 100% sure this is the correct generalization from single pixel thread rule to block rule var testRestartUpdate = (updateSum) * (newXExplore - (theta2 * oldXCorr + oldXExplore)); ConcurrentUpdateTestRestart(ref shared.testRestart, eta, testRestartUpdate); } //unlockBlock Thread.VolatileWrite(ref shared.BlockLock[blockIdx], 0); if (useAcceleration) { Theta = (float)(Math.Sqrt((theta2 * theta2) + 4 * (theta2)) - theta2) / 2.0f; } } Thread.VolatileWrite(ref shared.asyncFinished, 1); }
private static ReconstructionInfo Reconstruct(Data input, float fullLipschitz, float[,] maskedPsf, string folder, float maskFactor, int maxMajor, string dirtyPrefix, string xImagePrefix, StreamWriter writer, double objectiveCutoff, float epsilon, bool maskPsf2) { var info = new ReconstructionInfo(); var totalSize = new Rectangle(0, 0, input.c.GridSize, input.c.GridSize); var bMapCalculator = new PaddedConvolver(PSF.CalcPaddedFourierCorrelation(maskedPsf, totalSize), new Rectangle(0, 0, maskedPsf.GetLength(0), maskedPsf.GetLength(1))); var maskedPsf2 = PSF.CalcPSFSquared(maskedPsf); if (maskPsf2) { Mask(maskedPsf2, 1e-5f); } writer.WriteLine((CountNonZero(maskedPsf2) - maskedPsf2.Length) / (double)maskedPsf2.Length); var fastCD = new FastSerialCD(totalSize, totalSize, maskedPsf, maskedPsf2); FitsIO.Write(maskedPsf, folder + maskFactor + "psf.fits"); var lambda = 0.4f * fastCD.MaxLipschitz; var lambdaTrue = 0.4f * fullLipschitz; var alpha = 0.1f; var xImage = new float[input.c.GridSize, input.c.GridSize]; var residualVis = input.visibilities; DeconvolutionResult lastResult = null; for (int cycle = 0; cycle < maxMajor; cycle++) { Console.WriteLine("cycle " + cycle); var dirtyGrid = IDG.GridW(input.c, input.metadata, residualVis, input.uvw, input.frequencies); var dirtyImage = FFT.WStackIFFTFloat(dirtyGrid, input.c.VisibilitiesCount); FFT.Shift(dirtyImage); FitsIO.Write(dirtyImage, folder + dirtyPrefix + cycle + ".fits"); //calc data and reg penalty var dataPenalty = Residuals.CalcPenalty(dirtyImage); var regPenalty = ElasticNet.CalcPenalty(xImage, lambdaTrue, alpha); var regPenaltyCurrent = ElasticNet.CalcPenalty(xImage, lambda, alpha); info.lastDataPenalty = dataPenalty; info.lastRegPenalty = regPenalty; bMapCalculator.ConvolveInPlace(dirtyImage); //FitsIO.Write(dirtyImage, folder + dirtyPrefix + "bmap_" + cycle + ".fits"); var currentLambda = lambda; writer.Write(cycle + ";" + currentLambda + ";" + Residuals.GetMax(dirtyImage) + ";" + dataPenalty + ";" + regPenalty + ";" + regPenaltyCurrent + ";"); writer.Flush(); //check wether we can minimize the objective further with the current psf var objectiveReached = (dataPenalty + regPenalty) < objectiveCutoff; var minimumReached = (lastResult != null && lastResult.IterationCount < 100 && lastResult.Converged); if (!objectiveReached & !minimumReached) { info.totalDeconv.Start(); lastResult = fastCD.Deconvolve(xImage, dirtyImage, currentLambda, alpha, 50000, epsilon); info.totalDeconv.Stop(); FitsIO.Write(xImage, folder + xImagePrefix + cycle + ".fits"); writer.Write(lastResult.Converged + ";" + lastResult.IterationCount + ";" + lastResult.ElapsedTime.TotalSeconds + "\n"); writer.Flush(); FFT.Shift(xImage); var xGrid = FFT.Forward(xImage); FFT.Shift(xImage); var modelVis = IDG.DeGridW(input.c, input.metadata, xGrid, input.uvw, input.frequencies); residualVis = Visibilities.Substract(input.visibilities, modelVis, input.flags); } else { writer.Write(false + ";0;0"); writer.Flush(); break; } } return(info); }
private static ReconstructionInfo ReconstructGradientApprox(Data input, float[,] fullPsf, string folder, int cutFactor, int maxMajor, string dirtyPrefix, string xImagePrefix, StreamWriter writer, double objectiveCutoff, float epsilon) { var info = new ReconstructionInfo(); var psfCut = PSF.Cut(fullPsf, cutFactor); var maxSidelobe = PSF.CalcMaxSidelobe(fullPsf, cutFactor); var totalSize = new Rectangle(0, 0, input.c.GridSize, input.c.GridSize); var psfBMap = psfCut; var bMapCalculator = new PaddedConvolver(PSF.CalcPaddedFourierCorrelation(psfBMap, totalSize), new Rectangle(0, 0, psfBMap.GetLength(0), psfBMap.GetLength(1))); var bMapCalculator2 = new PaddedConvolver(PSF.CalcPaddedFourierCorrelation(fullPsf, totalSize), new Rectangle(0, 0, fullPsf.GetLength(0), fullPsf.GetLength(1))); var fastCD = new FastSerialCD(totalSize, psfCut); var fastCD2 = new FastSerialCD(totalSize, psfCut); fastCD2.ResetLipschitzMap(fullPsf); FitsIO.Write(psfCut, folder + cutFactor + "psf.fits"); var lambda = LAMBDA_GLOBAL * fastCD.MaxLipschitz; var lambdaTrue = (float)(LAMBDA_GLOBAL * PSF.CalcMaxLipschitz(fullPsf)); var xImage = new float[input.c.GridSize, input.c.GridSize]; var residualVis = input.visibilities; DeconvolutionResult lastResult = null; var firstTimeConverged = false; var lastLambda = 0.0f; for (int cycle = 0; cycle < maxMajor; cycle++) { Console.WriteLine("cycle " + cycle); var dirtyGrid = IDG.GridW(input.c, input.metadata, residualVis, input.uvw, input.frequencies); var dirtyImage = FFT.WStackIFFTFloat(dirtyGrid, input.c.VisibilitiesCount); FFT.Shift(dirtyImage); FitsIO.Write(dirtyImage, folder + dirtyPrefix + cycle + ".fits"); //calc data and reg penalty var dataPenalty = Residuals.CalcPenalty(dirtyImage); var regPenalty = ElasticNet.CalcPenalty(xImage, lambdaTrue, alpha); var regPenaltyCurrent = ElasticNet.CalcPenalty(xImage, lambda, alpha); info.lastDataPenalty = dataPenalty; info.lastRegPenalty = regPenalty; var maxDirty = Residuals.GetMax(dirtyImage); var bMap = bMapCalculator.Convolve(dirtyImage); FitsIO.Write(bMap, folder + dirtyPrefix + "bmap_" + cycle + ".fits"); var maxB = Residuals.GetMax(bMap); var correctionFactor = Math.Max(maxB / (maxDirty * fastCD.MaxLipschitz), 1.0f); var currentSideLobe = maxB * maxSidelobe * correctionFactor; var currentLambda = Math.Max(currentSideLobe / alpha, lambda); writer.Write(cycle + ";" + currentLambda + ";" + currentSideLobe + ";" + ";" + fastCD2.GetAbsMaxDiff(xImage, bMap, lambdaTrue, alpha) + ";" + dataPenalty + ";" + regPenalty + ";" + regPenaltyCurrent + ";");; writer.Flush(); //check wether we can minimize the objective further with the current psf var objectiveReached = (dataPenalty + regPenalty) < objectiveCutoff; var minimumReached = (lastResult != null && lastResult.Converged && fastCD2.GetAbsMaxDiff(xImage, dirtyImage, lambdaTrue, alpha) < MAJOR_EPSILON && currentLambda == lambda); if (lambda == lastLambda & !firstTimeConverged) { firstTimeConverged = true; minimumReached = false; } if (!objectiveReached & !minimumReached) { //writer.Write(firstTimeConverged + ";"); //writer.Flush(); info.totalDeconv.Start(); if (!firstTimeConverged) { lastResult = fastCD.Deconvolve(xImage, bMap, currentLambda, alpha, 30000, epsilon); } else { bMap = bMapCalculator2.Convolve(dirtyImage); //FitsIO.Write(bMap, folder + dirtyPrefix + "bmap_" + cycle + "_full.fits"); maxB = Residuals.GetMax(bMap); correctionFactor = Math.Max(maxB / (maxDirty * fastCD2.MaxLipschitz), 1.0f); currentSideLobe = maxB * maxSidelobe * correctionFactor; currentLambda = Math.Max(currentSideLobe / alpha, lambdaTrue); info.totalDeconv.Start(); lastResult = fastCD.Deconvolve(xImage, bMap, currentLambda, alpha, 30000, epsilon); info.totalDeconv.Stop(); } info.totalDeconv.Stop(); FitsIO.Write(xImage, folder + xImagePrefix + cycle + ".fits"); writer.Write(lastResult.Converged + ";" + lastResult.IterationCount + ";" + lastResult.ElapsedTime.TotalSeconds + "\n"); writer.Flush(); FFT.Shift(xImage); var xGrid = FFT.Forward(xImage); FFT.Shift(xImage); var modelVis = IDG.DeGridW(input.c, input.metadata, xGrid, input.uvw, input.frequencies); residualVis = Visibilities.Substract(input.visibilities, modelVis, input.flags); } else { writer.Write(false + ";0;0\n"); writer.Flush(); break; } lastLambda = currentLambda; } bMapCalculator.Dispose(); bMapCalculator2.Dispose(); return(info); }
public float DeconvolveAccelerated(float[,] xExplore, float[,] xCorrection, float[,] gExplore, float[,] gCorrection, float[,] psf2, ref List <Tuple <int, int> > activeSet, float maxLipschitz, float lambda, float alpha, Random random, int maxIteration, float epsilon) { var blockCount = activeSet.Count; var beta = CalcESO(tau, degreeOfSeperability, blockCount); var lipschitz = maxLipschitz * yBlockSize * xBlockSize; lipschitz *= (float)beta; var theta = tau / (float)blockCount; var theta0 = theta; float eta = 1.0f / blockCount; var testRestart = 0.0f; var iter = 0; var converged = false; Console.WriteLine("Starting Active Set iterations with " + activeSet.Count + " blocks"); while (iter < maxIteration & !converged) { var xDiffMax = new float[tau]; var innerIterCount = Math.Min(activeSet.Count / tau, MAX_ACTIVESET_ITER / tau); for (int inner = 0; inner < innerIterCount; inner++) { var stepSize = lipschitz * theta / theta0; var theta2 = theta * theta; var correctionFactor = -(1.0f - theta / theta0) / theta2; var samples = activeSet.Shuffle(random).Take(tau).ToList(); Parallel.For(0, tau, (i) => { var blockSample = samples[i]; var yOffset = blockSample.Item1 * yBlockSize; var xOffset = blockSample.Item2 * xBlockSize; var blockUpdate = new float[yBlockSize, xBlockSize]; var updateSum = 0.0f; var updateAbsSum = 0.0f; for (int y = yOffset; y < (yOffset + yBlockSize); y++) { for (int x = xOffset; x < (xOffset + xBlockSize); x++) { var update = theta2 * gCorrection[y, x] + gExplore[y, x] + xExplore[y, x] * stepSize; update = ElasticNet.ProximalOperator(update, stepSize, lambda, alpha) - xExplore[y, x]; blockUpdate[y - yOffset, x - xOffset] = update; updateSum = update; updateAbsSum += Math.Abs(update); } } //update gradients if (0.0f != updateAbsSum) { xDiffMax[i] = Math.Max(xDiffMax[i], updateAbsSum); UpdateBMaps(blockUpdate, blockSample.Item1, blockSample.Item2, psf2, gExplore, gCorrection, correctionFactor); var newXExplore = 0.0f; var oldXExplore = 0.0f; var oldXCorr = 0.0f; for (int y = yOffset; y < (yOffset + yBlockSize); y++) { for (int x = xOffset; x < (xOffset + xBlockSize); x++) { var update = blockUpdate[y - yOffset, x - xOffset]; var oldExplore = xExplore[y, x]; var oldCorrection = xCorrection[y, x]; oldXExplore += xExplore[y, x]; oldXCorr += xCorrection[y, x]; newXExplore += oldExplore + update; xExplore[y, x] += update; xCorrection[y, x] += update * correctionFactor; } } //not 100% sure this is the correct generalization from single pixel/single thread rule to block/parallel rule var testRestartUpdate = (updateSum) * (newXExplore - (theta2 * oldXCorr + oldXExplore)); ConcurrentUpdateTestRestart(ref testRestart, eta, testRestartUpdate); } }); theta = (float)(Math.Sqrt((theta2 * theta2) + 4 * (theta2)) - theta2) / 2.0f; } if (testRestart > 0) { //restart acceleration var tmpTheta = theta < 1.0f ? ((theta * theta) / (1.0f - theta)) : theta0; for (int y = 0; y < xExplore.GetLength(0); y++) { for (int x = 0; x < xExplore.GetLength(1); x++) { xExplore[y, x] += tmpTheta * xCorrection[y, x]; xCorrection[y, x] = 0; gExplore[y, x] += tmpTheta * gCorrection[y, x]; gCorrection[y, x] = 0; } } Console.WriteLine("restarting"); //new active set activeSet = GetActiveSet(xExplore, gExplore, lambda, alpha, maxLipschitz); blockCount = activeSet.Count; theta = tau / (float)blockCount; theta0 = theta; beta = CalcESO(tau, degreeOfSeperability, blockCount); lipschitz = maxLipschitz * yBlockSize * xBlockSize; lipschitz *= (float)beta; } if (xDiffMax.Sum() < epsilon) { converged = true; } Console.WriteLine("Done Active Set iteration " + iter); iter++; } return(theta); }
public bool DeconvolveGreedy(float[,] xImage, float[,] residuals, float[,] psf, float lambda, float alpha, Random random, int blockSize, int threadCount, int maxIteration = 100, float epsilon = 1e-4f) { var xExplore = Copy(xImage); var xCorrection = new float[xImage.GetLength(0), xImage.GetLength(1)]; var PSFCorr = PSF.CalcPaddedFourierCorrelation(psf, new Rectangle(0, 0, residuals.GetLength(0), residuals.GetLength(1))); //calculate gradients for each pixel var gExplore = Residuals.CalcGradientMap(residuals, PSFCorr, new Rectangle(0, 0, psf.GetLength(0), psf.GetLength(1))); var gCorrection = new float[residuals.GetLength(0), residuals.GetLength(1)]; var psf2 = PSF.CalcPSFSquared(psf); FitsIO.Write(gExplore, "gExplore.fits"); yBlockSize = blockSize; xBlockSize = blockSize; degreeOfSeperability = CountNonZero(psf); tau = threadCount; //number of processors var maxLipschitz = (float)PSF.CalcMaxLipschitz(psf); var theta = Greedy(xExplore, xCorrection, gExplore, gCorrection, psf2, maxLipschitz, lambda, alpha, random, maxIteration, epsilon); //decide which version should be taken# var CONVKernel = PSF.CalcPaddedFourierConvolution(psf, new Rectangle(0, 0, residuals.GetLength(0), residuals.GetLength(1))); var residualsCalculator = new PaddedConvolver(CONVKernel, new Rectangle(0, 0, psf.GetLength(0), psf.GetLength(1))); var theta0 = tau / (float)(xExplore.Length / (yBlockSize * xBlockSize)); var tmpTheta = theta < 1.0f ? ((theta * theta) / (1.0f - theta)) : theta0; //calculate residuals var residualsExplore = Copy(xExplore); var residualsAccelerated = Copy(xExplore); for (int i = 0; i < xImage.GetLength(0); i++) { for (int j = 0; j < xImage.GetLength(1); j++) { residualsExplore[i, j] -= xImage[i, j]; residualsAccelerated[i, j] += tmpTheta * xCorrection[i, j] - xImage[i, j]; xCorrection[i, j] = tmpTheta * xCorrection[i, j] + xExplore[i, j]; } } FitsIO.Write(xExplore, "xExplore.fits"); FitsIO.Write(xCorrection, "xAcc.fits"); residualsCalculator.ConvolveInPlace(residualsExplore); residualsCalculator.ConvolveInPlace(residualsAccelerated); for (int i = 0; i < xImage.GetLength(0); i++) { for (int j = 0; j < xImage.GetLength(1); j++) { residualsExplore[i, j] -= residuals[i, j]; residualsAccelerated[i, j] -= residuals[i, j]; } } var objectiveExplore = Residuals.CalcPenalty(residualsExplore) + ElasticNet.CalcPenalty(xExplore, lambda, alpha); var objectiveAcc = Residuals.CalcPenalty(residualsAccelerated) + ElasticNet.CalcPenalty(xCorrection, lambda, alpha); if (objectiveAcc < objectiveExplore) { for (int i = 0; i < xImage.GetLength(0); i++) { for (int j = 0; j < xImage.GetLength(1); j++) { xImage[i, j] = xCorrection[i, j]; } } } else { for (int i = 0; i < xImage.GetLength(0); i++) { for (int j = 0; j < xImage.GetLength(1); j++) { xImage[i, j] = xExplore[i, j]; } } } return(objectiveAcc < objectiveExplore); }
public static void DebugSimulatedApprox() { 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 double norm = 2.0; var visibilities = FitsIO.ReadVisibilities(@"C:\dev\GitHub\p9-data\small\fits\simulation_point\vis.fits", uvw.GetLength(0), uvw.GetLength(1), frequencies.Length, norm); var visibilitiesCount = visibilities.Length; int gridSize = 256; int subgridsize = 8; int kernelSize = 4; int max_nr_timesteps = 1024; double cellSize = 1.0 / 3600.0 * PI / 180.0; var c = new GriddingConstants(visibilitiesCount, gridSize, subgridsize, kernelSize, max_nr_timesteps, (float)cellSize, 1, 0.0f); var watchTotal = new Stopwatch(); var watchForward = new Stopwatch(); var watchBackwards = new Stopwatch(); var watchDeconv = new Stopwatch(); watchTotal.Start(); var metadata = Partitioner.CreatePartition(c, uvw, frequencies); var psfGrid = IDG.GridPSF(c, metadata, uvw, flags, frequencies); var psf = FFT.BackwardFloat(psfGrid, c.VisibilitiesCount); FFT.Shift(psf); var psfCut = PSF.Cut(psf); FitsIO.Write(psfCut, "psfCut.fits"); var random = new Random(123); var totalSize = new Rectangle(0, 0, gridSize, gridSize); var bMapCalculator = new PaddedConvolver(PSF.CalcPaddedFourierCorrelation(psfCut, totalSize), new Rectangle(0, 0, psfCut.GetLength(0), psfCut.GetLength(1))); var fastCD = new FastSerialCD(totalSize, psfCut); //fastCD.ResetAMap(psf); var lambda = 0.5f * fastCD.MaxLipschitz; var alpha = 0.8f; var approx = new ApproxParallel(); var approx2 = new ApproxFast(totalSize, psfCut, 4, 8, 0f, 0.25f, false, true); var xImage = new float[gridSize, gridSize]; var residualVis = visibilities; /*var truth = new double[gridSize, gridSize]; * truth[30, 30] = 1.0; * truth[35, 36] = 1.5; * var truthVis = IDG.ToVisibilities(c, metadata, truth, uvw, frequencies); * visibilities = truthVis; * var residualVis = truthVis;*/ var data = new ApproxFast.TestingData(new StreamWriter("approxConvergence.txt")); for (int cycle = 0; cycle < 4; cycle++) { //FORWARD watchForward.Start(); var dirtyGrid = IDG.Grid(c, metadata, residualVis, uvw, frequencies); var dirtyImage = FFT.BackwardFloat(dirtyGrid, c.VisibilitiesCount); FFT.Shift(dirtyImage); FitsIO.Write(dirtyImage, "dirty_" + cycle + ".fits"); watchForward.Stop(); //DECONVOLVE watchDeconv.Start(); //approx.ISTAStep(xImage, dirtyImage, psf, lambda, alpha); //FitsIO.Write(xImage, "xIsta.fits"); //FitsIO.Write(dirtyImage, "dirtyFista.fits"); //bMapCalculator.ConvolveInPlace(dirtyImage); //FitsIO.Write(dirtyImage, "bMap_" + cycle + ".fits"); //var result = fastCD.Deconvolve(xImage, dirtyImage, 0.5f * fastCD.MaxLipschitz, 0.8f, 1000, 1e-4f); //var converged = approx.DeconvolveActiveSet(xImage, dirtyImage, psfCut, lambda, alpha, random, 8, 1, 1); //var converged = approx.DeconvolveGreedy(xImage, dirtyImage, psfCut, lambda, alpha, random, 4, 4, 500); //var converged = approx.DeconvolveApprox(xImage, dirtyImage, psfCut, lambda, alpha, random, 1, threads, 500, 1e-4f, cycle == 0); approx2.DeconvolveTest(data, cycle, 0, xImage, dirtyImage, psfCut, psf, lambda, alpha, random, 10, 1e-4f); if (data.converged) { Console.WriteLine("-----------------------------CONVERGED!!!!------------------------"); } else { Console.WriteLine("-------------------------------not converged----------------------"); } FitsIO.Write(xImage, "xImageApprox_" + cycle + ".fits"); watchDeconv.Stop(); //BACKWARDS watchBackwards.Start(); FFT.Shift(xImage); var xGrid = FFT.Forward(xImage); FFT.Shift(xImage); var modelVis = IDG.DeGrid(c, metadata, xGrid, uvw, frequencies); residualVis = Visibilities.Substract(visibilities, modelVis, flags); watchBackwards.Stop(); } var dirtyGridCheck = IDG.Grid(c, metadata, residualVis, uvw, frequencies); var dirtyCheck = FFT.Backward(dirtyGridCheck, c.VisibilitiesCount); FFT.Shift(dirtyCheck); var l2Penalty = Residuals.CalcPenalty(ToFloatImage(dirtyCheck)); var elasticPenalty = ElasticNet.CalcPenalty(xImage, (float)lambda, (float)alpha); var sum = l2Penalty + elasticPenalty; data.writer.Close(); }
public float DeconvolveRandomActiveSet(float[,] xExplore, float[,] xCorrection, float[,] gExplore, float[,] gCorrection, float[,] psf2, ref List <Tuple <int, int> > activeSet, float maxLipschitz, float lambda, float alpha, Random random, int maxIteration, float epsilon) { var blockCount = activeSet.Count; var beta = CalcESO(tau, degreeOfSeperability, blockCount); var lipschitz = maxLipschitz * yBlockSize * xBlockSize; lipschitz *= (float)beta; var theta = tau / (float)blockCount; var theta0 = theta; float eta = 1.0f / blockCount; var testRestart = 0.0; var iter = 0; var blocks = new float[tau, yBlockSize, xBlockSize]; var containsNonZero = new bool[tau]; var converged = false; Console.WriteLine("Starting Active Set iterations with " + activeSet.Count + " blocks"); while (iter < maxIteration & !converged) { var xDiffMax = 0.0f; for (int inner = 0; inner < Math.Min(activeSet.Count / tau, 10000 / tau); inner++) { var stepSize = lipschitz * theta / theta0; var theta2 = theta * theta; var samples = CreateSamples(blockCount, tau, random); //minimize blocks for (int i = 0; i < samples.Length; i++) { var blockSample = activeSet[samples[i]]; var yOffset = blockSample.Item1 * yBlockSize; var xOffset = blockSample.Item2 * xBlockSize; containsNonZero[i] = false; for (int y = yOffset; y < (yOffset + yBlockSize); y++) { for (int x = xOffset; x < (xOffset + xBlockSize); x++) { var update = theta2 * gCorrection[y, x] + gExplore[y, x] + xExplore[y, x] * stepSize; update = ElasticNet.ProximalOperator(update, stepSize, lambda, alpha) - xExplore[y, x]; blocks[i, y - yOffset, x - xOffset] = update; if (update != 0.0) { containsNonZero[i] = true; } } } } //update bMaps var correctionFactor = -(1.0f - theta / theta0) / (theta * theta); for (int i = 0; i < samples.Length; i++) { if (containsNonZero[i]) { var blockSample = activeSet[samples[i]]; var yBlock = blockSample.Item1; var xBlock = blockSample.Item2; UpdateBMaps(i, blocks, yBlock, xBlock, psf2, gExplore, gCorrection, correctionFactor); //FitsIO.Write(gExplore, "gExplore2.fits"); //FitsIO.Write(gCorrection, "gCorr2.fits"); var currentDiff = 0.0f; //update reconstructed image var yOffset = yBlock * yBlockSize; var xOffset = xBlock * xBlockSize; for (int y = 0; y < blocks.GetLength(1); y++) { for (int x = 0; x < blocks.GetLength(2); x++) { var update = blocks[i, y, x]; var oldExplore = xExplore[yOffset + y, xOffset + x]; var oldCorrection = xCorrection[yOffset + y, xOffset + x]; var newValue = oldExplore + update; testRestart = (1.0 - eta) * testRestart - eta * (update) * (newValue - (theta * theta * oldCorrection + oldExplore)); currentDiff += Math.Abs(update); xExplore[yOffset + y, xOffset + x] += update; xCorrection[yOffset + y, xOffset + x] += update * correctionFactor; } } xDiffMax = Math.Max(xDiffMax, currentDiff); } } theta = (float)(Math.Sqrt((theta * theta * theta * theta) + 4 * (theta * theta)) - theta * theta) / 2.0f; } if (testRestart > 0) { //restart acceleration var tmpTheta = theta < 1.0f ? ((theta * theta) / (1.0f - theta)) : theta0; for (int y = 0; y < xExplore.GetLength(0); y++) { for (int x = 0; x < xExplore.GetLength(1); x++) { xExplore[y, x] += tmpTheta * xCorrection[y, x]; xCorrection[y, x] = 0; gExplore[y, x] += tmpTheta * gCorrection[y, x]; gCorrection[y, x] = 0; } } Console.WriteLine("restarting"); //new active set activeSet = GetActiveSet(xExplore, gExplore, lambda, alpha, maxLipschitz); blockCount = activeSet.Count; theta = tau / (float)blockCount; theta0 = theta; beta = CalcESO(tau, degreeOfSeperability, blockCount); lipschitz = maxLipschitz * yBlockSize * xBlockSize; lipschitz *= (float)beta; } if (xDiffMax < epsilon) { //converged = true; } Console.WriteLine("Done Active Set iteration " + iter); iter++; } return(theta); }
private static void ReconstructPCDM(MeasurementData input, GriddingConstants c, float[,] fullPsf, string folder, string file, int minorCycles, float searchPercent, int processorCount) { var totalWatch = new Stopwatch(); var currentWatch = new Stopwatch(); var totalSize = new Rectangle(0, 0, c.GridSize, c.GridSize); var psfCut = PSF.Cut(fullPsf, CUT_FACTOR_PCDM); var maxSidelobe = PSF.CalcMaxSidelobe(fullPsf, CUT_FACTOR_PCDM); var sidelobeHalf = PSF.CalcMaxSidelobe(fullPsf, 2); var random = new Random(123); var pcdm = new ParallelCoordinateDescent(totalSize, psfCut, 1, 1000, searchPercent); var metadata = Partitioner.CreatePartition(c, input.UVW, input.Frequencies); using (var bMapCalculator = new PaddedConvolver(PSF.CalcPaddedFourierCorrelation(psfCut, totalSize), new Rectangle(0, 0, psfCut.GetLength(0), psfCut.GetLength(1)))) using (var bMapCalculator2 = new PaddedConvolver(PSF.CalcPaddedFourierCorrelation(fullPsf, totalSize), new Rectangle(0, 0, fullPsf.GetLength(0), fullPsf.GetLength(1)))) using (var residualsConvolver = new PaddedConvolver(totalSize, fullPsf)) { var currentBMapCalculator = bMapCalculator; var maxLipschitz = PSF.CalcMaxLipschitz(psfCut); var lambda = (float)(LAMBDA * maxLipschitz); var lambdaTrue = (float)(LAMBDA * PSF.CalcMaxLipschitz(fullPsf)); var alpha = ALPHA; var switchedToOtherPsf = false; var writer = new StreamWriter(folder + "/" + file + ".txt"); var xImage = new float[c.GridSize, c.GridSize]; var residualVis = input.Visibilities; ParallelCoordinateDescent.PCDMStatistics lastResult = null; for (int cycle = 0; cycle < 6; cycle++) { Console.WriteLine("Beginning Major cycle " + cycle); var dirtyGrid = IDG.GridW(c, metadata, residualVis, input.UVW, input.Frequencies); var dirtyImage = FFT.WStackIFFTFloat(dirtyGrid, c.VisibilitiesCount); FFT.Shift(dirtyImage); FitsIO.Write(dirtyImage, folder + "/dirty" + cycle + ".fits"); currentWatch.Restart(); totalWatch.Start(); var breakMajor = false; var minLambda = 0.0f; var dirtyCopy = Copy(dirtyImage); var xCopy = Copy(xImage); var currentLambda = 0f; var currentObjective = 0.0; var absMax = 0.0f; for (int minorCycle = 0; minorCycle < minorCycles; minorCycle++) { Console.WriteLine("Beginning Minor Cycle " + minorCycle); var maxDirty = Residuals.GetMax(dirtyImage); var bMap = currentBMapCalculator.Convolve(dirtyImage); var maxB = Residuals.GetMax(bMap); var correctionFactor = Math.Max(maxB / (maxDirty * maxLipschitz), 1.0f); var currentSideLobe = maxB * maxSidelobe * correctionFactor; currentLambda = (float)Math.Max(currentSideLobe / alpha, lambda); if (minorCycle == 0) { minLambda = (float)(maxB * sidelobeHalf * correctionFactor / alpha); } if (currentLambda < minLambda) { currentLambda = minLambda; } currentObjective = Residuals.CalcPenalty(dirtyImage) + ElasticNet.CalcPenalty(xImage, lambdaTrue, alpha); absMax = pcdm.GetAbsMax(xImage, bMap, lambdaTrue, alpha); if (absMax < MAJOR_STOP) { breakMajor = true; break; } lastResult = pcdm.Deconvolve(xImage, bMap, currentLambda, alpha, 100, 1e-5f); if (currentLambda == lambda | currentLambda == minLambda) { break; } var residualsUpdate = new float[xImage.GetLength(0), xImage.GetLength(1)]; Parallel.For(0, xCopy.GetLength(0), (i) => { for (int j = 0; j < xCopy.GetLength(1); j++) { residualsUpdate[i, j] = xImage[i, j] - xCopy[i, j]; } }); residualsConvolver.ConvolveInPlace(residualsUpdate); Parallel.For(0, xCopy.GetLength(0), (i) => { for (int j = 0; j < xCopy.GetLength(1); j++) { dirtyImage[i, j] = dirtyCopy[i, j] - residualsUpdate[i, j]; } }); } currentWatch.Stop(); totalWatch.Stop(); writer.WriteLine(cycle + ";" + currentLambda + ";" + currentObjective + ";" + absMax + ";" + lastResult.IterationCount + ";" + totalWatch.Elapsed.TotalSeconds + ";" + currentWatch.Elapsed.TotalSeconds); writer.Flush(); FitsIO.Write(xImage, folder + "/xImage_pcdm_" + cycle + ".fits"); if (breakMajor) { break; } if (currentLambda == lambda & !switchedToOtherPsf) { pcdm.ResetAMap(fullPsf); currentBMapCalculator = bMapCalculator2; lambda = lambdaTrue; switchedToOtherPsf = true; writer.WriteLine("switched"); writer.Flush(); } FFT.Shift(xImage); var xGrid = FFT.Forward(xImage); FFT.Shift(xImage); var modelVis = IDG.DeGridW(c, metadata, xGrid, input.UVW, input.Frequencies); residualVis = Visibilities.Substract(input.Visibilities, modelVis, input.Flags); } writer.Close(); } }
/// <summary> /// Major cycle implemnentation for the parallel coordinate descent algorithm /// </summary> /// <param name="data"></param> /// <param name="c"></param> /// <param name="psfCutFactor"></param> /// <param name="maxMajorCycle"></param> /// <param name="maxMinorCycle"></param> /// <param name="lambda"></param> /// <param name="alpha"></param> /// <param name="deconvIterations"></param> /// <param name="deconvEpsilon"></param> public static void ReconstructPCDM(string obsName, MeasurementData data, GriddingConstants c, int psfCutFactor, int maxMajorCycle, int maxMinorCycle, float lambda, float alpha, int deconvIterations, float deconvEpsilon) { var metadata = Partitioner.CreatePartition(c, data.UVW, data.Frequencies); var psfVis = new Complex[data.UVW.GetLength(0), data.UVW.GetLength(1), data.Frequencies.Length]; for (int i = 0; i < data.Visibilities.GetLength(0); i++) { for (int j = 0; j < data.Visibilities.GetLength(1); j++) { for (int k = 0; k < data.Visibilities.GetLength(2); k++) { if (!data.Flags[i, j, k]) { psfVis[i, j, k] = new Complex(1.0, 0); } else { psfVis[i, j, k] = new Complex(0, 0); } } } } Console.WriteLine("gridding psf"); var psfGrid = IDG.Grid(c, metadata, psfVis, data.UVW, data.Frequencies); var psf = FFT.BackwardFloat(psfGrid, c.VisibilitiesCount); FFT.Shift(psf); var totalWatch = new Stopwatch(); var currentWatch = new Stopwatch(); var totalSize = new Rectangle(0, 0, c.GridSize, c.GridSize); var psfCut = PSF.Cut(psf, psfCutFactor); var maxSidelobe = PSF.CalcMaxSidelobe(psf, psfCutFactor); var sidelobeHalf = PSF.CalcMaxSidelobe(psf, 2); var pcdm = new ParallelCoordinateDescent(totalSize, psfCut, Environment.ProcessorCount, 1000); using (var gCalculator = new PaddedConvolver(PSF.CalcPaddedFourierCorrelation(psfCut, totalSize), new Rectangle(0, 0, psfCut.GetLength(0), psfCut.GetLength(1)))) using (var gCalculator2 = new PaddedConvolver(PSF.CalcPaddedFourierCorrelation(psf, totalSize), new Rectangle(0, 0, psf.GetLength(0), psf.GetLength(1)))) using (var residualsConvolver = new PaddedConvolver(totalSize, psf)) { var currentGCalculator = gCalculator; var maxLipschitz = PSF.CalcMaxLipschitz(psfCut); var lambdaLipschitz = (float)(lambda * maxLipschitz); var lambdaTrue = (float)(lambda * PSF.CalcMaxLipschitz(psf)); var switchedToOtherPsf = false; var xImage = new float[c.GridSize, c.GridSize]; var residualVis = data.Visibilities; ParallelCoordinateDescent.PCDMStatistics lastResult = null; for (int cycle = 0; cycle < maxMajorCycle; cycle++) { Console.WriteLine("Beginning Major cycle " + cycle); var dirtyGrid = IDG.GridW(c, metadata, residualVis, data.UVW, data.Frequencies); var dirtyImage = FFT.WStackIFFTFloat(dirtyGrid, c.VisibilitiesCount); FFT.Shift(dirtyImage); FitsIO.Write(dirtyImage, obsName + "_dirty_pcdm_majorCycle" + cycle + ".fits"); currentWatch.Restart(); totalWatch.Start(); var breakMajor = false; var minLambda = 0.0f; var dirtyCopy = Copy(dirtyImage); var xCopy = Copy(xImage); var currentLambda = 0f; var currentObjective = 0.0; var absMax = 0.0f; for (int minorCycle = 0; minorCycle < maxMinorCycle; minorCycle++) { Console.WriteLine("Beginning Minor Cycle " + minorCycle); var maxDirty = Residuals.GetMax(dirtyImage); var bMap = currentGCalculator.Convolve(dirtyImage); var maxB = Residuals.GetMax(bMap); var correctionFactor = Math.Max(maxB / (maxDirty * maxLipschitz), 1.0f); var currentSideLobe = maxB * maxSidelobe * correctionFactor; currentLambda = (float)Math.Max(currentSideLobe / alpha, lambdaLipschitz); if (minorCycle == 0) { minLambda = (float)(maxB * sidelobeHalf * correctionFactor / alpha); } if (currentLambda < minLambda) { currentLambda = minLambda; } currentObjective = Residuals.CalcPenalty(dirtyImage) + ElasticNet.CalcPenalty(xImage, lambdaTrue, alpha); absMax = pcdm.GetAbsMax(xImage, bMap, lambdaTrue, alpha); if (absMax < MAJOR_EPSILON) { breakMajor = true; break; } lastResult = pcdm.Deconvolve(xImage, bMap, currentLambda, alpha, 40, deconvEpsilon); if (currentLambda == lambda | currentLambda == minLambda) { break; } var residualsUpdate = new float[xImage.GetLength(0), xImage.GetLength(1)]; Parallel.For(0, xCopy.GetLength(0), (i) => { for (int j = 0; j < xCopy.GetLength(1); j++) { residualsUpdate[i, j] = xImage[i, j] - xCopy[i, j]; } }); residualsConvolver.ConvolveInPlace(residualsUpdate); Parallel.For(0, xCopy.GetLength(0), (i) => { for (int j = 0; j < xCopy.GetLength(1); j++) { dirtyImage[i, j] = dirtyCopy[i, j] - residualsUpdate[i, j]; } }); } currentWatch.Stop(); totalWatch.Stop(); if (breakMajor) { break; } if (currentLambda == lambda & !switchedToOtherPsf) { pcdm.ResetAMap(psf); currentGCalculator = gCalculator2; lambda = lambdaTrue; switchedToOtherPsf = true; } FitsIO.Write(xImage, obsName + "_model_pcdm_majorCycle" + cycle + ".fits"); FFT.Shift(xImage); var xGrid = FFT.Forward(xImage); FFT.Shift(xImage); var modelVis = IDG.DeGridW(c, metadata, xGrid, data.UVW, data.Frequencies); residualVis = Visibilities.Substract(data.Visibilities, modelVis, data.Flags); } Console.WriteLine("Reconstruction finished in (seconds): " + totalWatch.Elapsed.TotalSeconds); } }
/// <summary> /// Major cycle implementation for the Serial CD /// </summary> /// <param name="obsName"></param> /// <param name="data"></param> /// <param name="c"></param> /// <param name="useGPU"></param> /// <param name="psfCutFactor"></param> /// <param name="maxMajorCycle"></param> /// <param name="lambda"></param> /// <param name="alpha"></param> /// <param name="deconvIterations"></param> /// <param name="deconvEpsilon"></param> public static void ReconstructSerialCD(string obsName, MeasurementData data, GriddingConstants c, bool useGPU, int psfCutFactor, int maxMajorCycle, float lambda, float alpha, int deconvIterations, float deconvEpsilon) { var metadata = Partitioner.CreatePartition(c, data.UVW, data.Frequencies); var psfVis = new Complex[data.UVW.GetLength(0), data.UVW.GetLength(1), data.Frequencies.Length]; for (int i = 0; i < data.Visibilities.GetLength(0); i++) { for (int j = 0; j < data.Visibilities.GetLength(1); j++) { for (int k = 0; k < data.Visibilities.GetLength(2); k++) { if (!data.Flags[i, j, k]) { psfVis[i, j, k] = new Complex(1.0, 0); } else { psfVis[i, j, k] = new Complex(0, 0); } } } } Console.WriteLine("gridding psf"); var psfGrid = IDG.GridW(c, metadata, psfVis, data.UVW, data.Frequencies); var psf = FFT.WStackIFFTFloat(psfGrid, c.VisibilitiesCount); FFT.Shift(psf); var totalWatch = new Stopwatch(); var currentWatch = new Stopwatch(); var totalSize = new Rectangle(0, 0, c.GridSize, c.GridSize); var psfCut = PSF.Cut(psf, psfCutFactor); var maxSidelobe = PSF.CalcMaxSidelobe(psf, psfCutFactor); IDeconvolver deconvolver = null; if (useGPU & GPUSerialCD.IsGPUSupported()) { deconvolver = new GPUSerialCD(totalSize, psfCut, 1000); } else if (useGPU & !GPUSerialCD.IsGPUSupported()) { Console.WriteLine("GPU not supported by library. Switching to CPU implementation"); deconvolver = new FastSerialCD(totalSize, psfCut); } else { deconvolver = new FastSerialCD(totalSize, psfCut); } var psfBMap = psfCut; using (var gCalculator = new PaddedConvolver(PSF.CalcPaddedFourierCorrelation(psfBMap, totalSize), new Rectangle(0, 0, psfBMap.GetLength(0), psfBMap.GetLength(1)))) using (var gCalculator2 = new PaddedConvolver(PSF.CalcPaddedFourierCorrelation(psf, totalSize), new Rectangle(0, 0, psf.GetLength(0), psf.GetLength(1)))) { var currentGCalculator = gCalculator; var maxLipschitz = PSF.CalcMaxLipschitz(psfCut); var lambdaLipschitz = (float)(lambda * maxLipschitz); var lambdaTrue = (float)(lambda * PSF.CalcMaxLipschitz(psf)); var switchedToOtherPsf = false; var xImage = new float[c.GridSize, c.GridSize]; var residualVis = data.Visibilities; DeconvolutionResult lastResult = null; for (int cycle = 0; cycle < maxMajorCycle; cycle++) { Console.WriteLine("Beginning Major cycle " + cycle); var dirtyGrid = IDG.GridW(c, metadata, residualVis, data.UVW, data.Frequencies); var dirtyImage = FFT.WStackIFFTFloat(dirtyGrid, c.VisibilitiesCount); FFT.Shift(dirtyImage); FitsIO.Write(dirtyImage, obsName + "_dirty_serial_majorCycle" + cycle + ".fits"); currentWatch.Restart(); totalWatch.Start(); var maxDirty = Residuals.GetMax(dirtyImage); var gradients = gCalculator.Convolve(dirtyImage); var maxB = Residuals.GetMax(gradients); var correctionFactor = Math.Max(maxB / (maxDirty * maxLipschitz), 1.0f); var currentSideLobe = maxB * maxSidelobe * correctionFactor; var currentLambda = (float)Math.Max(currentSideLobe / alpha, lambdaLipschitz); var objective = Residuals.CalcPenalty(dirtyImage) + ElasticNet.CalcPenalty(xImage, lambdaTrue, alpha); var absMax = deconvolver.GetAbsMaxDiff(xImage, gradients, lambdaTrue, alpha); if (absMax >= MAJOR_EPSILON) { lastResult = deconvolver.Deconvolve(xImage, gradients, currentLambda, alpha, deconvIterations, deconvEpsilon); } if (lambda == currentLambda & !switchedToOtherPsf) { currentGCalculator = gCalculator2; lambda = lambdaTrue; maxLipschitz = PSF.CalcMaxLipschitz(psf); switchedToOtherPsf = true; } FitsIO.Write(xImage, obsName + "_model_serial_majorCycle" + cycle + ".fits"); currentWatch.Stop(); totalWatch.Stop(); if (absMax < MAJOR_EPSILON) { break; } FFT.Shift(xImage); var xGrid = FFT.Forward(xImage); FFT.Shift(xImage); var modelVis = IDG.DeGridW(c, metadata, xGrid, data.UVW, data.Frequencies); residualVis = Visibilities.Substract(data.Visibilities, modelVis, data.Flags); } Console.WriteLine("Reconstruction finished in (seconds): " + totalWatch.Elapsed.TotalSeconds); } }