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"); } }