public override void NextFrame(int frameNo, IAstroImage astroImage) { IsTrackedSuccessfully = false; // For each of the non manualy positioned Tracked objects do a PSF fit in the area of its previous location for (int i = 0; i < m_TrackedObjectGroups.Count; i++) { TrackedObjectGroup objectGroup = m_TrackedObjectGroups[i]; objectGroup.NextFrame(); if (objectGroup.TrackLater) { // Group position will be determined after the rest of the stars are found } else { if (objectGroup.IsSingleObject) { TrackedObjectLight trackedObject = (TrackedObjectLight) objectGroup.SingleObject; uint[,] pixels = astroImage.GetPixelsArea(objectGroup.SingleObjectLastCenter.X, objectGroup.SingleObjectLastCenter.Y, 17); var fit = new PSFFit(objectGroup.SingleObjectLastCenter.X, objectGroup.SingleObjectLastCenter.Y); fit.FittingMethod = PSFFittingMethod.NonLinearFit; fit.Fit(pixels); if (fit.IsSolved) { if (fit.Certainty < GUIDING_STAR_MIN_CERTAINTY) { trackedObject.SetIsTracked(false, NotMeasuredReasons.ObjectCertaintyTooSmall); } else if (fit.FWHM < STELLAR_OBJECT_MIN_FWHM || fit.FWHM > STELLAR_OBJECT_MAX_FWHM) { trackedObject.SetIsTracked(false, NotMeasuredReasons.FWHMOutOfRange); } else if (TangraConfig.Settings.Tracking.CheckElongation && fit.ElongationPercentage > STELLAR_OBJECT_MAX_ELONGATION) { trackedObject.SetIsTracked(false, NotMeasuredReasons.ObjectTooElongated); } else { trackedObject.SetTrackedObjectMatch(fit); trackedObject.SetIsTracked(true, NotMeasuredReasons.TrackedSuccessfully); } } } else { string dbg = ""; int areaCenterX = (objectGroup.LastCenterObject1.X + objectGroup.LastCenterObject2.X) / 2; int areaCenterY = (objectGroup.LastCenterObject1.Y + objectGroup.LastCenterObject2.Y) / 2; uint[,] pixels = astroImage.GetPixelsArea(areaCenterX, areaCenterY, 35); var doubleFit = new DoublePSFFit(areaCenterX, areaCenterY); int x1 = objectGroup.LastCenterObject1.X - areaCenterX + 17; int y1 = objectGroup.LastCenterObject1.Y - areaCenterY + 17; int x2 = objectGroup.LastCenterObject2.X - areaCenterX + 17; int y2 = objectGroup.LastCenterObject2.Y - areaCenterY + 17; if (TangraConfig.Settings.Photometry.PsfFittingMethod == TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel) doubleFit.FittingMethod = PSFFittingMethod.LinearFitOfAveragedModel; doubleFit.Fit(pixels, x1, y1, x2, y2); if (doubleFit.IsSolved) { PSFFit fit1 = doubleFit.GetGaussian1(); PSFFit fit2 = doubleFit.GetGaussian2(); TrackedObjectLight trackedObject1; TrackedObjectLight trackedObject2; bool groupIdentified = objectGroup.IdentifyObjects(fit1, fit2, GUIDING_STAR_MIN_CERTAINTY, out trackedObject1, out trackedObject2); if (!groupIdentified) { dbg += "Ni-"; objectGroup.SetIsTracked(false, NotMeasuredReasons.PSFFittingFailed); //Bitmap bmp = new Bitmap(100, 200); //using (Graphics g = Graphics.FromImage(bmp)) //{ // doubleFit.DrawInternalPoints(g, new Rectangle(0, 0, 100, 200), 5, 5, Brushes.Lime, Brushes.Yellow, 8); // g.Save(); //} //bmp.Save(@"D:\Hristo\mutual_double_fit.bmp"); m_FailedGroupFits++; } else { PSFFit[] fits = new PSFFit[] { fit1, fit2 }; TrackedObjectLight[] trackedObjects = new TrackedObjectLight[] { trackedObject1, trackedObject2 }; int tooSmallCertainties = 0; int errors = 0; for (int j = 0; j < 2; j++) { PSFFit fit = fits[j]; TrackedObjectLight trackedObject = trackedObjects[j]; if (fit.Certainty < GUIDING_STAR_MIN_CERTAINTY) { tooSmallCertainties++; trackedObject.SetIsTracked(true, NotMeasuredReasons.TrackedSuccessfully); dbg += "TsGs-"; } else if (fit.FWHM < STELLAR_OBJECT_MIN_FWHM || fit.FWHM > STELLAR_OBJECT_MAX_FWHM) { trackedObject.SetIsTracked(false, NotMeasuredReasons.FWHMOutOfRange); dbg += "Fw-"; errors++; } else if (TangraConfig.Settings.Tracking.CheckElongation && fit.ElongationPercentage > STELLAR_OBJECT_MAX_ELONGATION) { trackedObject.SetIsTracked(false, NotMeasuredReasons.ObjectTooElongated); dbg += "Elo-"; errors++; } else { trackedObject.SetIsTracked(true, NotMeasuredReasons.TrackedSuccessfully); dbg += "Ts-"; } } if (tooSmallCertainties == 2) { trackedObjects[0].SetIsTracked(false, NotMeasuredReasons.ObjectCertaintyTooSmall); trackedObjects[1].SetIsTracked(false, NotMeasuredReasons.ObjectCertaintyTooSmall); errors++; m_FailedGroupFits++; dbg += "Uncer-"; } if (errors == 0) { if (objectGroup.CheckIdentifiedObjects(fits[0].XCenter, fits[1].XCenter, fits[0].YCenter, fits[1].YCenter)) { trackedObjects[0].SetTrackedObjectMatch(fits[0]); trackedObjects[1].SetTrackedObjectMatch(fits[1]); m_FailedGroupFits = 0; dbg += "Id-"; double dist = ImagePixel.ComputeDistance(fits[0].XCenter, fits[1].XCenter, fits[0].YCenter, fits[1].YCenter); if (dist < 2) { Trace.WriteLine("TOO CLOSE"); } if (dist > 16) { Trace.WriteLine("TOO FAR"); } } else { dbg += "NoId-"; } } } } else dbg += "NoSlv-"; objectGroup.ValidatePosition(); Trace.WriteLine(dbg); } } } bool atLeastOneGroupLocated = false; for (int i = 0; i < m_TrackedObjectGroups.Count; i++) { TrackedObjectGroup trackedGroup = m_TrackedObjectGroups[i]; if (!trackedGroup.IsSingleObject && trackedGroup.LastCenterObject1 != null && trackedGroup.LastCenterObject2 != null) { Trace.WriteLine(string.Format("({0}, {1}, {2}) ({3},{4},{5}) [{6},{7}]", trackedGroup.LastCenterObject1.XDouble, trackedGroup.LastCenterObject1.YDouble, trackedGroup.LastCenterObject1.Brightness, trackedGroup.LastCenterObject2.XDouble, trackedGroup.LastCenterObject2.YDouble, trackedGroup.LastCenterObject2.Brightness, trackedGroup.LastCenterObject1.XDouble - trackedGroup.LastCenterObject2.XDouble, trackedGroup.LastCenterObject1.YDouble - trackedGroup.LastCenterObject2.YDouble)); } bool containsFullyDisappearingTarget = trackedGroup.ContainsOcultedStar && m_IsFullDisappearance; if (!containsFullyDisappearingTarget && trackedGroup.IsLocated) atLeastOneGroupLocated = true; if (!containsFullyDisappearingTarget) continue; int numReferences = 0; double x_double; double y_double; if (trackedGroup.IsSingleObject && m_IsFullDisappearance) { // This is the case for single fully disappearing targets double totalX = 0; double totalY = 0; numReferences = 0; for (int j = 0; j < m_TrackedObjectGroups.Count; j++) { TrackedObjectGroup referenceGroup = (TrackedObjectGroup)m_TrackedObjectGroups[j]; if (referenceGroup.IsLocated) { totalX += (trackedGroup.BrigherOriginalObject.ApertureStartingX - referenceGroup.BrigherOriginalObject.ApertureStartingX) + referenceGroup.BrigherObjectLastCenter.XDouble; totalY += (trackedGroup.BrigherOriginalObject.ApertureStartingY - referenceGroup.BrigherOriginalObject.ApertureStartingY) + referenceGroup.BrigherObjectLastCenter.YDouble; numReferences++; atLeastOneGroupLocated = true; } } x_double = totalX / numReferences; y_double = totalY / numReferences; } else { // The fully disappearing target is in a group. The other target would have been located. We use the last known position of the other targets numReferences = 1; x_double = trackedGroup.NonOccultedObjectLastCenter.XDouble; y_double = trackedGroup.NonOccultedObjectLastCenter.YDouble; } if (numReferences == 0) { trackedGroup.SetIsTracked(false, NotMeasuredReasons.FitSuspectAsNoGuidingStarsAreLocated); } else { int x = (int)(Math.Round(x_double)); int y = (int)(Math.Round(y_double)); uint[,] pixels = astroImage.GetPixelsArea(x, y, 35); if (trackedGroup.IsSingleObject) { PSFFit fit = new PSFFit(x, y); fit.Fit(pixels); if (fit.IsSolved && fit.Certainty > STELLAR_OBJECT_MIN_CERTAINTY) { trackedGroup.SingleObject.SetIsTracked(true, NotMeasuredReasons.TrackedSuccessfully); trackedGroup.SingleObject.SetTrackedObjectMatch(fit); } else if (m_IsFullDisappearance) trackedGroup.SingleObject.SetIsTracked(false, NotMeasuredReasons.FullyDisappearingStarMarkedTrackedWithoutBeingFound); else trackedGroup.SingleObject.SetIsTracked(false, NotMeasuredReasons.ObjectCertaintyTooSmall); } else { string dbg = ""; DoublePSFFit doubleFit = new DoublePSFFit(x, y); int x1 = trackedGroup.LastCenterObject1.X - x + 17; int y1 = trackedGroup.LastCenterObject1.Y - y + 17; int x2 = trackedGroup.LastCenterObject2.X - x + 17; int y2 = trackedGroup.LastCenterObject2.Y - y + 17; if (TangraConfig.Settings.Photometry.PsfFittingMethod == TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel) doubleFit.FittingMethod = PSFFittingMethod.LinearFitOfAveragedModel; doubleFit.Fit(pixels, x1, y1, x2, y2); if (doubleFit.IsSolved) { PSFFit fit1 = doubleFit.GetGaussian1(); PSFFit fit2 = doubleFit.GetGaussian2(); IImagePixel center1 = null; IImagePixel center2 = null; TrackedObjectLight trackedObject1; TrackedObjectLight trackedObject2; bool resortToBrightness = false; bool groupIdentified = trackedGroup.IdentifyObjects(fit1, fit2, GUIDING_STAR_MIN_CERTAINTY, out trackedObject1, out trackedObject2); if (!groupIdentified && m_IsFullDisappearance) { dbg += "ReBr::"; groupIdentified = trackedGroup.IdentifyBrightObject(fit1, fit2, STELLAR_OBJECT_MIN_CERTAINTY, out trackedObject1, out trackedObject2, out center1, out center2); resortToBrightness = true; } if (!groupIdentified) { trackedGroup.SetIsTracked(false, NotMeasuredReasons.PSFFittingFailed); dbg += "PsF::"; } else { PSFFit[] fits = new PSFFit[] { fit1, fit2 }; IImagePixel[] centers = new IImagePixel[] { center1, center2 }; TrackedObjectLight[] trackedObjects = new TrackedObjectLight[] { trackedObject1, trackedObject2 }; bool objectCheckSuccessful = resortToBrightness ? trackedGroup.CheckIdentifiedObjects(center1.XDouble, center2.XDouble, center1.YDouble, center2.YDouble) : trackedGroup.CheckIdentifiedObjects(fits[0].XCenter, fits[1].XCenter, fits[0].YCenter, fits[1].YCenter); if (objectCheckSuccessful) { dbg += "ChS::"; bool atLeastOneOK = (fit1.IsSolved && fit1.Certainty > GUIDING_STAR_MIN_CERTAINTY) || (fit2.IsSolved && fit2.Certainty > GUIDING_STAR_MIN_CERTAINTY); double dist = ImagePixel.ComputeDistance(fit1.XCenter, fit2.XCenter, fit1.YCenter, fit2.YCenter); if (!atLeastOneOK || ((dist < 2 || dist > 16) && !resortToBrightness)) { trackedGroup.SetIsTracked(false, NotMeasuredReasons.PSFFittingFailed); } int cntOk = 0; for (int j = 0; j < 2; j++) { PSFFit fit = fits[j]; IImagePixel center = centers[j]; TrackedObjectLight trackedObject = trackedObjects[j]; if (fit.IsSolved && fit.Certainty > STELLAR_OBJECT_MIN_CERTAINTY) { if (resortToBrightness && trackedObject.IsOccultedStar) { trackedObject.SetIsTracked(true, NotMeasuredReasons.FullyDisappearingStarMarkedTrackedWithoutBeingFound, center, fit.Certainty); dbg += "OccDi::"; } else { trackedObject.SetTrackedObjectMatch(fit); trackedObject.SetIsTracked(true, NotMeasuredReasons.TrackedSuccessfully); dbg += "TrSuc::"; } cntOk++; } else if (m_IsFullDisappearance && trackedObject.IsOccultedStar) { trackedObject.SetIsTracked(false, NotMeasuredReasons.FullyDisappearingStarMarkedTrackedWithoutBeingFound, resortToBrightness ? center : null, 1); dbg += "BadCerSuc::"; } else { trackedObject.SetIsTracked(false, NotMeasuredReasons.ObjectCertaintyTooSmall, resortToBrightness ? center : null, resortToBrightness ? fit.Certainty : (double?)null); dbg += "BadCerNOSuc::"; } } if (cntOk == 2) { m_FailedGroupFits = 0; } } else { trackedObjects[0].SetIsTracked(false, NotMeasuredReasons.FailedToLocateAfterDistanceCheck); trackedObjects[1].SetIsTracked(false, NotMeasuredReasons.FailedToLocateAfterDistanceCheck); m_FailedGroupFits++; dbg += "ChU::"; } } } else { m_FailedGroupFits++; dbg += "NoFi::"; } trackedGroup.ValidatePosition(); Trace.WriteLine(dbg); } } } IsTrackedSuccessfully = atLeastOneGroupLocated; if (IsTrackedSuccessfully) RefinedAverageFWHM = m_TrackedObjects.Cast<TrackedObjectLight>().Average(x => x.RefinedFWHM); if (m_FailedGroupFits > 10) { Trace.WriteLine("ERR~10+"); } }
private void CalculateTwoObjectsPSFs() { if (m_AutoDoubleCenter != null) { m_Center = new ImagePixel(m_AutoDoubleCenter); m_X1Start = m_AutoDoubleX1Start; m_Y1Start = m_AutoDoubleY1Start; m_X2Start = m_AutoDoubleX2Start; m_Y2Start = m_AutoDoubleY2Start; m_ProcessingPixels = m_AstroImage.GetMeasurableAreaPixels(m_Center.X, m_Center.Y, 35); m_DisplayPixels = m_AstroImage.GetMeasurableAreaDisplayBitmapPixels(m_Center.X, m_Center.Y, 35); } if (!m_UserPeakMode && !FirstObjectPeakDefined() && !SecondObjectPeakDefined() && !LocatePeaks()) { m_UserPeakMode = true; MessageBox.Show( this, "Please click on the image to define the center of each of the two objects.", "Tangra", MessageBoxButtons.OK, MessageBoxIcon.Question); picTarget1Pixels.Cursor = Cursors.Cross; UpdateViews(); return; } if (!FirstObjectPeakDefined() || !SecondObjectPeakDefined()) { MessageBox.Show( this, "Cannot locate two objects.", "Tangra", MessageBoxButtons.OK, MessageBoxIcon.Error); } var psfFit = new DoublePSFFit(m_Center.X, m_Center.Y); if (TangraConfig.Settings.Photometry.PsfFittingMethod == TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel) psfFit.FittingMethod = PSFFittingMethod.LinearFitOfAveragedModel; psfFit.Fit(m_ProcessingPixels, m_X1Start, m_Y1Start, m_X2Start, m_Y2Start); if (psfFit.IsSolved) { m_DoubleGaussian = psfFit; m_FWHM = (float)psfFit.FWHM; m_X0 = psfFit.X0_Matrix; m_Y0 = psfFit.Y0_Matrix; m_FWHM1 = (float)psfFit.FWHM1; m_FWHM2 = (float)psfFit.FWHM2; m_X1 = psfFit.X1_Matrix; m_Y1 = psfFit.Y1_Matrix; m_X2 = psfFit.X2_Matrix; m_Y2 = psfFit.Y2_Matrix; m_X1Center = (float)psfFit.X1Center; m_Y1Center = (float)psfFit.Y1Center; m_X2Center = (float)psfFit.X2Center; m_Y2Center = (float)psfFit.Y2Center; if (m_Aperture1 == null) { if (TangraConfig.Settings.Photometry.SignalApertureUnitDefault == TangraConfig.SignalApertureUnit.FWHM) m_Aperture1 = (float)(psfFit.FWHM1 * TangraConfig.Settings.Photometry.DefaultSignalAperture); else m_Aperture1 = (float)(TangraConfig.Settings.Photometry.DefaultSignalAperture); } else if ( TangraConfig.Settings.Photometry.SignalApertureUnitDefault == TangraConfig.SignalApertureUnit.FWHM && m_Aperture1 < (float)(psfFit.FWHM1 * TangraConfig.Settings.Photometry.DefaultSignalAperture)) { // When the default aperture size is in FWHM we always use the largest aperture so far m_Aperture1 = (float)(psfFit.FWHM1 * TangraConfig.Settings.Photometry.DefaultSignalAperture); } if (m_Aperture2 == null) { if (TangraConfig.Settings.Photometry.SignalApertureUnitDefault == TangraConfig.SignalApertureUnit.FWHM) m_Aperture2 = (float)(psfFit.FWHM2 * TangraConfig.Settings.Photometry.DefaultSignalAperture); else m_Aperture2 = (float)(TangraConfig.Settings.Photometry.DefaultSignalAperture); } else if ( TangraConfig.Settings.Photometry.SignalApertureUnitDefault == TangraConfig.SignalApertureUnit.FWHM && m_Aperture2 < (float)(psfFit.FWHM2 * TangraConfig.Settings.Photometry.DefaultSignalAperture)) { // When the default aperture size is in FWHM we always use the largest aperture so far m_Aperture2 = (float) (psfFit.FWHM2*TangraConfig.Settings.Photometry.DefaultSignalAperture); } if (m_Aperture1 > m_Aperture2) m_Aperture2 = m_Aperture1; if (m_Aperture2 > m_Aperture1) m_Aperture1 = m_Aperture2; nudAperture1.SetNUDValue(m_Aperture1.Value); m_Aperture = null; m_Gaussian = null; } }
private bool IsGoodDoubleObjectFit(Tuple<int, int, uint> object1, Tuple<int, int, uint> object2) { var doubleFit = new DoublePSFFit(100, 100); if (TangraConfig.Settings.Photometry.PsfFittingMethod == TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel) doubleFit.FittingMethod = PSFFittingMethod.LinearFitOfAveragedModel; doubleFit.Fit(m_ProcessingPixels, object1.Item1, object1.Item2, object2.Item1, object2.Item2); if (doubleFit.IsSolved && Math.Abs(doubleFit.FWHM1 - doubleFit.FWHM2) < Math.Max(1, Math.Min(doubleFit.FWHM1, doubleFit.FWHM2)*0.25) && doubleFit.IAmplitude1 > 0 && doubleFit.IAmplitude2 > 0) { double imaxRatio = doubleFit.IAmplitude1 / doubleFit.IAmplitude2; if (imaxRatio > 1) imaxRatio = 1 / imaxRatio; if (imaxRatio >= 0.25) { // We require at least 1:4 ratio in the maximums for the auto-detection to accept that it has found correctly two objects double distance = ImagePixel.ComputeDistance(object1.Item1, object2.Item1, object1.Item2, object2.Item2); if (distance > doubleFit.FWHM1 && distance > doubleFit.FWHM2) { // We also require at least a FWHM distance between centers for automatic detection m_X1Start = object1.Item1; m_Y1Start = object1.Item2; m_X2Start = object2.Item1; m_Y2Start = object2.Item2; return true; } } return false; } return false; }
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"); }