internal NotMeasuredReasons DoLinearProfileFittingOfAveragedMoodelPhotometry( PSFFit fit, uint[,] matrix, int x0Int, int y0Int, float x0, float y0, float modelFWHM, float aperture, int matrixSize, bool useNumericalQadrature, bool isFullyDisappearingOccultedStar, uint[,] backgroundArea, bool mayBeOcculted /* Some magic based on a pure guess */, float bgAnnulusFactor, IBackgroundModelProvider backgroundModel) { double distance = ImagePixel.ComputeDistance(fit.XCenter, x0, fit.YCenter, y0); double tolerance = isFullyDisappearingOccultedStar ? m_TimesHigherPositionToleranceForFullyOccultedStars * m_PositionTolerance : m_PositionTolerance; // We first go and do the measurement anyway if (fit.IsSolved) { SetPsfFitReading(fit, aperture, useNumericalQadrature, backgroundArea, bgAnnulusFactor, backgroundModel); } else { m_Aperture = aperture; m_XCenter = (float)fit.X0_Matrix; m_YCenter = (float)fit.Y0_Matrix; m_TotalReading = 0; m_TotalBackground = 0; } if (!fit.IsSolved || // The PSF solution failed, mark the reading invalid (distance > tolerance && !mayBeOcculted) // If this doesn't look like a full disappearance, then make the reading invalid ) { return(!fit.IsSolved ? NotMeasuredReasons.MeasurementPSFFittingFailed : NotMeasuredReasons.DistanceToleranceTooHighForNonFullDisappearingOccultedStar); } else { return(NotMeasuredReasons.MeasuredSuccessfully); } }
public void Fit(uint[,] intensity, IBackgroundModelProvider backgroundModel, int x1start, int y1start, int x2start, int y2start) { m_BackgroundModel = backgroundModel; try { if (FittingMethod == PSFFittingMethod.NonLinearFit) { NonLinearFit(intensity, x1start, y1start, x2start, y2start, TangraConfig.Settings.Tuning.PsfMode == TangraConfig.PSFFittingMode.NativeMatrixManagedFitting); } else if (FittingMethod == PSFFittingMethod.NonLinearAsymetricFit) { throw new NotSupportedException(); } else if (FittingMethod == PSFFittingMethod.LinearFitOfAveragedModel) { LinearFitOfAveragedModel(intensity, x1start, y1start, x2start, y2start, TangraConfig.Settings.Tuning.PsfMode == TangraConfig.PSFFittingMode.NativeMatrixManagedFitting); } } catch (Exception) { // singular matrix, etc m_IsSolved = false; } }
public void Fit(uint[,] intensity, IBackgroundModelProvider backgroundModel, int x1start, int y1start, int x2start, int y2start) { m_BackgroundModel = backgroundModel; try { if (FittingMethod == PSFFittingMethod.NonLinearFit) NonLinearFit(intensity, x1start, y1start, x2start, y2start, TangraConfig.Settings.Tuning.PsfMode == TangraConfig.PSFFittingMode.NativeMatrixManagedFitting); else if (FittingMethod == PSFFittingMethod.NonLinearAsymetricFit) throw new NotSupportedException(); else if (FittingMethod == PSFFittingMethod.LinearFitOfAveragedModel) LinearFitOfAveragedModel(intensity, x1start, y1start, x2start, y2start, TangraConfig.Settings.Tuning.PsfMode == TangraConfig.PSFFittingMode.NativeMatrixManagedFitting); } catch (Exception) { // singular matrix, etc m_IsSolved = false; } }
private double Get3DPolynomialBackground(uint[,] backgroundArea, float aperture, double x0, double y0, IBackgroundModelProvider backgroundModel) { int side = backgroundArea.GetLength(0); float totalBgPixels = 0; return(GetReading( aperture, backgroundArea, side, side, (float)x0, (float)y0, (x, y) => backgroundModel.ComputeValue(x, y), ref totalBgPixels)); }
private void SetPsfFitReading(PSFFit fit, float aperture, bool useNumericalQadrature, uint[,] backgroundArea, float bgAnnulusFactor, IBackgroundModelProvider backgroundModel = null) { m_Aperture = aperture; m_XCenter = (float)fit.X0_Matrix; m_YCenter = (float)fit.Y0_Matrix; if (useNumericalQadrature) { double r0Square = fit.R0 * fit.R0; m_TotalReading = Integration.IntegrationOverCircularArea( delegate(double x, double y) { double combinedValue = fit.I0 + (fit.IMax - fit.I0) * Math.Exp((-x * x + -y * y) / r0Square); if (fit.UsesBackgroundModel) { return(combinedValue + fit.GetFittedBackgroundModelValue(x, y)); } else { return(combinedValue); } }, m_Aperture); if (m_BackgroundMethod == TangraConfig.BackgroundMethod.PSFBackground) { m_TotalBackground = Math.PI * m_Aperture * m_Aperture * fit.I0; } else if (m_BackgroundMethod == TangraConfig.BackgroundMethod.Background3DPolynomial) { if (!fit.UsesBackgroundModel && backgroundModel == null) { throw new InvalidOperationException("3D-Polynomial was not applied correctly."); } int offset = (35 - fit.MatrixSize) / 2; m_TotalBackground = Integration.IntegrationOverCircularArea( (x, y) => fit.UsesBackgroundModel ? fit.GetFittedBackgroundModelValue(x, y) : backgroundModel.ComputeValue(x + offset, y + offset), m_Aperture); } else { int offset = (35 - fit.MatrixSize) / 2; double bgFromAnnulus = GetBackground(backgroundArea, m_Aperture, m_XCenter + offset, m_YCenter + offset, bgAnnulusFactor); m_TotalBackground = Math.PI * m_Aperture * m_Aperture * (float)bgFromAnnulus; } } else { // Analytical quadrature (Gauss Integral) if (m_BackgroundMethod == TangraConfig.BackgroundMethod.PSFBackground) { m_TotalReading = (fit.IMax - fit.I0) * fit.R0 * fit.R0 * Math.PI; m_TotalBackground = 0; // The background has been already included in the TotalReading } else if (m_BackgroundMethod == TangraConfig.BackgroundMethod.Background3DPolynomial) { if (!fit.UsesBackgroundModel) { throw new InvalidOperationException("3D-Polynomial was not applied correctly."); } m_TotalReading = (fit.IMax - fit.I0) * fit.R0 * fit.R0 * Math.PI; m_TotalBackground = 0; // The background has been already included in the TotalReading } else { throw new InvalidOperationException("Analytical quadrature only works with PSFBackground and Background3DPolynomial."); } } }
internal NotMeasuredReasons DoAperturePhotometry( uint[,] matrix, int x0Int, int y0Int, float x0, float y0, float aperture, int matrixSize, uint[,] backgroundArea, float bgAnnulusFactor, IBackgroundModelProvider backgroundModel, int centerX = 0, int centerY = 0) { if (matrix.GetLength(0) != 17 && matrix.GetLength(0) != 35) { throw new ApplicationException("Measurement error. Correlation: AFP-101"); } int side = matrix.GetLength(0); float halfSide = 1.0f * side / 2f; m_HasSaturatedPixels = false; m_PSFBackground = double.NaN; m_FoundBestPSFFit = null; m_XCenter = x0 - x0Int + halfSide; m_YCenter = y0 - y0Int + halfSide; m_Aperture = aperture; m_PixelData = matrix; m_TotalPixels = 0; m_TotalReading = GetReading( m_Aperture, m_PixelData, side, side, m_XCenter, m_YCenter, null, ref m_TotalPixels, centerX - 8, centerY - 8); if (m_TotalPixels > 0) { if (m_BackgroundMethod == TangraConfig.BackgroundMethod.PSFBackground) { PSFFit fit = new PSFFit(x0Int, y0Int); fit.Fit(matrix, matrixSize); if (!fit.IsSolved) { m_TotalBackground = 0; } else { m_TotalBackground = (uint)Math.Round(m_TotalPixels * (float)fit.I0); } } else if (m_BackgroundMethod == TangraConfig.BackgroundMethod.Background3DPolynomial) { int offset = (35 - side) / 2; m_TotalBackground = Get3DPolynomialBackground(backgroundArea, m_Aperture, m_XCenter + offset, m_YCenter + offset, backgroundModel); } else if (m_BackgroundMethod != TangraConfig.BackgroundMethod.PSFBackground) { int offset = (35 - side) / 2; if (GetImagePixelsCallback != null) { backgroundArea = GetImagePixelsCallback(x0Int, y0Int, 71); offset += 17; } double bgFromAnnulus = GetBackground(backgroundArea, m_Aperture, m_XCenter + offset, m_YCenter + offset, bgAnnulusFactor); m_TotalBackground = (uint)Math.Round(m_TotalPixels * (float)bgFromAnnulus); } else { throw new ApplicationException("Measurement error. Correlation: AFP-102"); } return(NotMeasuredReasons.MeasuredSuccessfully); } else { m_TotalBackground = 0; m_TotalReading = 0; return(NotMeasuredReasons.NoPixelsToMeasure); } }
public NotMeasuredReasons MeasureObject( IImagePixel center, uint[,] data, uint[,] backgroundPixels, int bpp, TangraConfig.PreProcessingFilter filter, TangraConfig.PhotometryReductionMethod reductionMethod, TangraConfig.PsfQuadrature psfQuadrature, TangraConfig.PsfFittingMethod psfFittingMethod, float aperture, double refinedFWHM, float refinedAverageFWHM, IMeasurableObject measurableObject, IImagePixel[] objectsInGroup, float[] aperturesInGroup, bool fullDisappearance) { // NOTE: This is how the center of the pixel area passed in data and background arrays is determined // TODO: Pass the center as an argument int centerX = (int)Math.Round(center.XDouble); int centerY = (int)Math.Round(center.YDouble); float msrX0 = (float)center.XDouble; float msrY0 = (float)center.YDouble; float bgAnnulusFactor = 1; switch (filter) { case TangraConfig.PreProcessingFilter.LowPassFilter: data = ImageFilters.LowPassFilter(data, bpp, true); backgroundPixels = ImageFilters.LowPassFilter(backgroundPixels, bpp, true); break; case TangraConfig.PreProcessingFilter.LowPassDifferenceFilter: data = ImageFilters.LowPassDifferenceFilter(data, bpp, true); backgroundPixels = ImageFilters.LowPassDifferenceFilter(backgroundPixels, bpp, true); break; default: break; } float modelFWHM = float.NaN; if (psfFittingMethod == TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel) { if (TangraConfig.Settings.Photometry.UseUserSpecifiedFWHM) { modelFWHM = TangraConfig.Settings.Photometry.UserSpecifiedFWHM; } else { modelFWHM = refinedAverageFWHM; } } DoublePSFFit doublefit = null; PSFFit fit = null; IBackgroundModelProvider backgroundModel = null; // 1 - Fit a PSF to the current obejct if (objectsInGroup != null && objectsInGroup.Length == 2) { // 1A - When this is a star group int x1 = (int)Math.Round((data.GetLength(0) / 2) + objectsInGroup[0].XDouble - center.XDouble); int y1 = (int)Math.Round((data.GetLength(0) / 2) + objectsInGroup[0].YDouble - center.YDouble); int x2 = (int)Math.Round((data.GetLength(0) / 2) + objectsInGroup[1].XDouble - center.XDouble); int y2 = (int)Math.Round((data.GetLength(0) / 2) + objectsInGroup[1].YDouble - center.YDouble); doublefit = new DoublePSFFit(centerX, centerY); if (psfFittingMethod == TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel && !float.IsNaN(modelFWHM)) { doublefit.FittingMethod = PSFFittingMethod.LinearFitOfAveragedModel; doublefit.SetAveragedModelFWHM(modelFWHM); } doublefit.Fit(data, x1, y1, x2, y2); PSFFit star1 = doublefit.GetGaussian1(); PSFFit star2 = doublefit.GetGaussian2(); if (m_BackgroundMethod == TangraConfig.BackgroundMethod.Background3DPolynomial) { var bg3dFit = new Background3DPolynomialFit(); bg3dFit.Fit(data, star1, star2); doublefit.Fit(data, bg3dFit, x1, y1, x2, y2); star1 = doublefit.GetGaussian1(); star2 = doublefit.GetGaussian2(); backgroundModel = bg3dFit; } double d1 = ImagePixel.ComputeDistance(measurableObject.Center.XDouble, doublefit.X1Center, measurableObject.Center.YDouble, doublefit.Y1Center); double d2 = ImagePixel.ComputeDistance(measurableObject.Center.XDouble, doublefit.X2Center, measurableObject.Center.YDouble, doublefit.Y2Center); fit = (d1 < d2) ? star1 : star2; if (reductionMethod == TangraConfig.PhotometryReductionMethod.AperturePhotometry) { // NOTE: If aperture photometry is used, we measure the double object in a single larger aperture centered at the middle double alpha = Math.Atan((star2.YCenter - star1.YCenter) / (star2.XCenter - star1.XCenter)); float dx = (float)((star1.FWHM - star2.FWHM) * Math.Cos(alpha)); float dy = (float)((star1.FWHM - star2.FWHM) * Math.Sin(alpha)); msrX0 = (float)(star1.XCenter - star1.FWHM + star2.XCenter + star2.FWHM) / 2.0f - dx; msrY0 = (float)(star1.YCenter - star1.FWHM + star2.YCenter + star2.FWHM) / 2.0f - dy; aperture = aperturesInGroup.Sum(); bgAnnulusFactor = 0.67f; } } else if (reductionMethod != TangraConfig.PhotometryReductionMethod.AperturePhotometry) { // 1B - When this is a single star fit = new PSFFit(centerX, centerY); if (psfFittingMethod == TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel && !float.IsNaN(modelFWHM)) { fit.FittingMethod = PSFFittingMethod.LinearFitOfAveragedModel; fit.SetAveragedModelFWHM(modelFWHM); } fit.Fit(data, measurableObject.PsfFittingMatrixSize); if (m_BackgroundMethod == TangraConfig.BackgroundMethod.Background3DPolynomial) { // If 3D Poly Background is used then fit the background, and supply it to the PSF Fitting var bg3dFit = new Background3DPolynomialFit(); bg3dFit.Fit(backgroundPixels, fit, null); backgroundModel = bg3dFit; if (psfFittingMethod != TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel) { /* 3D Poly modelling works in a direct fit only with non-linear fitting */ fit.Fit(backgroundPixels, bg3dFit, measurableObject.PsfFittingMatrixSize); } } } else if ( reductionMethod == TangraConfig.PhotometryReductionMethod.AperturePhotometry && m_BackgroundMethod == TangraConfig.BackgroundMethod.Background3DPolynomial) { // 1C - Single star with aperture photometry and 3D Poly Background var bg3dFit = new Background3DPolynomialFit(); bg3dFit.Fit(backgroundPixels, (float)(centerX - msrX0 + 17), (float)(centerY - msrY0 + 17), 2 * aperture); backgroundModel = bg3dFit; } // 2 - Do the actual photometric measurements (signal and background) based on the selected methods if (reductionMethod == TangraConfig.PhotometryReductionMethod.PsfPhotometry) { // 2A - PSF Photometry if (TangraConfig.Settings.Photometry.PsfFittingMethod == TangraConfig.PsfFittingMethod.DirectNonLinearFit) { return(DoNonLinearProfileFittingPhotometry( fit, data, centerX, centerY, msrX0, msrY0, aperture, measurableObject.PsfFittingMatrixSize, psfQuadrature == TangraConfig.PsfQuadrature.NumericalInAperture, measurableObject.IsOccultedStar && fullDisappearance, backgroundPixels, measurableObject.MayHaveDisappeared, refinedFWHM, bgAnnulusFactor)); } else if (psfFittingMethod == TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel) { return(DoLinearProfileFittingOfAveragedMoodelPhotometry( fit, data, centerX, centerY, msrX0, msrY0, modelFWHM, aperture, measurableObject.PsfFittingMatrixSize, psfQuadrature == TangraConfig.PsfQuadrature.NumericalInAperture, measurableObject.IsOccultedStar && fullDisappearance, backgroundPixels, measurableObject.MayHaveDisappeared, bgAnnulusFactor, backgroundModel)); } else { throw new NotImplementedException(); } } else if (reductionMethod == TangraConfig.PhotometryReductionMethod.AperturePhotometry) { return(DoAperturePhotometry( data, centerX, centerY, msrX0, msrY0, aperture, measurableObject.PsfFittingMatrixSize, backgroundPixels, bgAnnulusFactor, backgroundModel, measurableObject.Center.X, measurableObject.Center.Y)); } else if (reductionMethod == TangraConfig.PhotometryReductionMethod.OptimalExtraction) { return(DoOptimalExtractionPhotometry( fit, data, centerX, centerY, msrX0, msrY0, aperture, measurableObject.PsfFittingMatrixSize, measurableObject.IsOccultedStar && fullDisappearance, backgroundPixels, measurableObject.MayHaveDisappeared, refinedFWHM, bgAnnulusFactor)); } else { throw new ArgumentOutOfRangeException("reductionMethod"); } }
public void Fit(uint[,] intensity, IBackgroundModelProvider backgroundModel, int newMatrixSize) { m_BackgroundModel = backgroundModel; m_UsesBackgroundModel = m_BackgroundModel != null; m_BackgroundModelOffset = 0; if (newMatrixSize == 17 || newMatrixSize == 35 || newMatrixSize == 0) { Fit(intensity); } else if (newMatrixSize < 17 && intensity.GetLength(0) == 17) { uint[,] newData = new uint[newMatrixSize,newMatrixSize]; int halfSize = newMatrixSize/2; m_BackgroundModelOffset = (intensity.GetLength(0) - newMatrixSize) / 2; int xx = 0, yy = 0; for (int y = 9 - halfSize - 1; y <= 9 + halfSize - 1; y++) { xx = 0; for (int x = 9 - halfSize - 1; x <= 9 + halfSize - 1; x++) { newData[xx, yy] = intensity[x, y]; xx++; } yy++; } Fit(newData); } else if (newMatrixSize < 35 && intensity.GetLength(0) == 35) { uint[,] newData = new uint[newMatrixSize, newMatrixSize]; int halfSize = newMatrixSize / 2; m_BackgroundModelOffset = (intensity.GetLength(0) - newMatrixSize) / 2; int xx = 0, yy = 0; for (int y = 18 - halfSize - 1; y <= 18 + halfSize - 1; y++) { xx = 0; for (int x = 18 - halfSize - 1; x <= 18 + halfSize - 1; x++) { newData[xx, yy] = intensity[x, y]; xx++; } yy++; } Fit(newData); } else if (newMatrixSize < 33 && intensity.GetLength(0) == 33 /* Digital Filter in use */) { uint[,] newData = new uint[newMatrixSize, newMatrixSize]; int halfSize = newMatrixSize / 2; m_BackgroundModelOffset = (intensity.GetLength(0) - newMatrixSize) / 2; int xx = 0, yy = 0; for (int y = 17 - halfSize - 1; y <= 17 + halfSize - 1; y++) { xx = 0; for (int x = 17 - halfSize - 1; x <= 17 + halfSize - 1; x++) { newData[xx, yy] = intensity[x, y]; xx++; } yy++; } Fit(newData); } else throw new InvalidOperationException("Bad matrix size."); }
private double Get3DPolynomialBackground(uint[,] backgroundArea, float aperture, double x0, double y0, IBackgroundModelProvider backgroundModel) { int side = backgroundArea.GetLength(0); float totalBgPixels = 0; return GetReading( aperture, backgroundArea, side, side, (float)x0, (float)y0, (x, y) => backgroundModel.ComputeValue(x, y), ref totalBgPixels); }
internal NotMeasuredReasons DoLinearProfileFittingOfAveragedMoodelPhotometry( PSFFit fit, uint[,] matrix, int x0Int, int y0Int, float x0, float y0, float modelFWHM, float aperture, int matrixSize, bool useNumericalQadrature, bool isFullyDisappearingOccultedStar, uint[,] backgroundArea, bool mayBeOcculted /* Some magic based on a pure guess */, float bgAnnulusFactor, IBackgroundModelProvider backgroundModel) { double distance = ImagePixel.ComputeDistance(fit.XCenter, x0, fit.YCenter, y0); double tolerance = isFullyDisappearingOccultedStar ? m_TimesHigherPositionToleranceForFullyOccultedStars * m_PositionTolerance : m_PositionTolerance; // We first go and do the measurement anyway if (fit.IsSolved) SetPsfFitReading(fit, aperture, useNumericalQadrature, backgroundArea, bgAnnulusFactor, backgroundModel); else { m_Aperture = aperture; m_XCenter = (float)fit.X0_Matrix; m_YCenter = (float)fit.Y0_Matrix; m_TotalReading = 0; m_TotalBackground = 0; } if (!fit.IsSolved || // The PSF solution failed, mark the reading invalid (distance > tolerance && !mayBeOcculted)// If this doesn't look like a full disappearance, then make the reading invalid ) { return !fit.IsSolved ? NotMeasuredReasons.MeasurementPSFFittingFailed : NotMeasuredReasons.DistanceToleranceTooHighForNonFullDisappearingOccultedStar; } else return NotMeasuredReasons.MeasuredSuccessfully; }
internal NotMeasuredReasons DoAperturePhotometry( uint[,] matrix, int x0Int, int y0Int, float x0, float y0, float aperture, int matrixSize, uint[,] backgroundArea, float bgAnnulusFactor, IBackgroundModelProvider backgroundModel, int centerX = 0, int centerY = 0) { if (matrix.GetLength(0) != 17 && matrix.GetLength(0) != 35) throw new ApplicationException("Measurement error. Correlation: AFP-101"); int side = matrix.GetLength(0); float halfSide = 1.0f*side / 2f; m_HasSaturatedPixels = false; m_PSFBackground = double.NaN; m_FoundBestPSFFit = null; m_XCenter = x0 - x0Int + halfSide; m_YCenter = y0 - y0Int + halfSide; m_Aperture = aperture; m_PixelData = matrix; m_TotalPixels = 0; m_TotalReading = GetReading( m_Aperture, m_PixelData, side, side, m_XCenter, m_YCenter, null, ref m_TotalPixels, centerX - 8, centerY - 8); if (m_TotalPixels > 0) { if (m_BackgroundMethod == TangraConfig.BackgroundMethod.PSFBackground) { PSFFit fit = new PSFFit(x0Int, y0Int); fit.Fit(matrix, matrixSize); if (!fit.IsSolved) m_TotalBackground = 0; else m_TotalBackground = (uint)Math.Round(m_TotalPixels * (float)fit.I0); } else if (m_BackgroundMethod == TangraConfig.BackgroundMethod.Background3DPolynomial) { int offset = (35 - side) / 2; m_TotalBackground = Get3DPolynomialBackground(backgroundArea, m_Aperture, m_XCenter + offset, m_YCenter + offset, backgroundModel); } else if (m_BackgroundMethod != TangraConfig.BackgroundMethod.PSFBackground) { int offset = (35 - side) / 2; if (GetImagePixelsCallback != null) { backgroundArea = GetImagePixelsCallback(x0Int, y0Int, 71); side = 34; offset = (71 - side) / 2; } double bgFromAnnulus = GetBackground(backgroundArea, m_Aperture, m_XCenter + offset, m_YCenter + offset, bgAnnulusFactor); m_TotalBackground = (uint) Math.Round(m_TotalPixels*(float) bgFromAnnulus); } else { throw new ApplicationException("Measurement error. Correlation: AFP-102"); } return NotMeasuredReasons.MeasuredSuccessfully; } else { m_TotalBackground = 0; m_TotalReading = 0; return NotMeasuredReasons.NoPixelsToMeasure; } }
private void SetPsfFitReading(PSFFit fit, float aperture, bool useNumericalQadrature, uint[,] backgroundArea, float bgAnnulusFactor, IBackgroundModelProvider backgroundModel = null) { m_Aperture = aperture; m_XCenter = (float)fit.X0_Matrix; m_YCenter = (float)fit.Y0_Matrix; if (useNumericalQadrature) { double r0Square = fit.R0 * fit.R0; m_TotalReading = Integration.IntegrationOverCircularArea( delegate(double x, double y) { double combinedValue = fit.I0 + (fit.IMax - fit.I0) * Math.Exp((-x * x + -y * y) / r0Square); if (fit.UsesBackgroundModel) return combinedValue + fit.GetFittedBackgroundModelValue(x, y); else return combinedValue; }, m_Aperture); if (m_BackgroundMethod == TangraConfig.BackgroundMethod.PSFBackground) { m_TotalBackground = Math.PI * m_Aperture * m_Aperture * fit.I0; } else if (m_BackgroundMethod == TangraConfig.BackgroundMethod.Background3DPolynomial) { if (!fit.UsesBackgroundModel && backgroundModel == null) throw new InvalidOperationException("3D-Polynomial was not applied correctly."); int offset = (35 - fit.MatrixSize) / 2; m_TotalBackground = Integration.IntegrationOverCircularArea( (x, y) => fit.UsesBackgroundModel ? fit.GetFittedBackgroundModelValue(x, y) : backgroundModel.ComputeValue(x + offset, y + offset), m_Aperture); } else { int offset = (35 - fit.MatrixSize) / 2; double bgFromAnnulus = GetBackground(backgroundArea, m_Aperture, m_XCenter + offset, m_YCenter + offset, bgAnnulusFactor); m_TotalBackground = Math.PI * m_Aperture * m_Aperture * (float)bgFromAnnulus; } } else { // Analytical quadrature (Gauss Integral) if (m_BackgroundMethod == TangraConfig.BackgroundMethod.PSFBackground) { m_TotalReading = (fit.IMax - fit.I0) * fit.R0 * fit.R0 * Math.PI; m_TotalBackground = 0; // The background has been already included in the TotalReading } else if (m_BackgroundMethod == TangraConfig.BackgroundMethod.Background3DPolynomial) { if (!fit.UsesBackgroundModel) throw new InvalidOperationException("3D-Polynomial was not applied correctly."); m_TotalReading = (fit.IMax - fit.I0) * fit.R0 * fit.R0 * Math.PI; m_TotalBackground = 0; // The background has been already included in the TotalReading } else { throw new InvalidOperationException("Analytical quadrature only works with PSFBackground and Background3DPolynomial."); } } }