public void SetComboboxIndexFromPsfQuadratureMethod(TangraConfig.PsfQuadrature method) { switch (method) { case TangraConfig.PsfQuadrature.NumericalInAperture: cbxPsfQuadrature.SelectedIndex = 0; break; case TangraConfig.PsfQuadrature.Analytical: cbxPsfQuadrature.SelectedIndex = 1; break; default: cbxPsfQuadrature.SelectedIndex = 0; break; } }
private NotMeasuredReasons MeasureObject( IImagePixel center, uint[,] data, uint[,] backgroundPixels, int bpp, MeasurementsHelper measurer, TangraConfig.PreProcessingFilter filter, TangraConfig.PhotometryReductionMethod reductionMethod, TangraConfig.PsfQuadrature psfQuadrature, TangraConfig.PsfFittingMethod psfFittngMethod, float aperture, double refinedFWHM, float refinedAverageFWHM, IMeasurableObject measurableObject, IImagePixel[] groupCenters, float[] aperturesInGroup, bool fullDisappearance ) { return(measurer.MeasureObject( center, data, backgroundPixels, bpp, filter, reductionMethod, psfQuadrature, psfFittngMethod, aperture, refinedFWHM, refinedAverageFWHM, measurableObject, groupCenters, aperturesInGroup, fullDisappearance)); }
public StarMagnitudeFit( AstroImage astroImage, int bitPix, List<double> intencities, List<double> magnitudes, List<double> colours, List<IStar> starNumbers, List<PSFFit> psfGaussians, List<double> profileFittedAmplitudes, List<bool> saturatedFlags, double a, double b, double c, float encodingGamma, TangraConfig.KnownCameraResponse reverseCameraResponse, int excludedStars, TangraConfig.PreProcessingFilter filter, double empericalFWHM, TangraConfig.PhotometryReductionMethod photometryReductionMethod, TangraConfig.BackgroundMethod photometryBackgroundMethod, TangraConfig.PsfQuadrature psfQuadrature, TangraConfig.PsfFittingMethod psfFittingMethod, MeasurementsHelper measurer, float? aperture) { m_CurrentAstroImage = astroImage; m_BitPix = bitPix; m_Intencities = intencities; m_Magnitudes = magnitudes; m_Colours = colours; m_Residuals = new List<double>(); m_StarNumbers = starNumbers; m_PSFGaussians = psfGaussians; m_EncodingGamma = encodingGamma; m_ReverseCameraResponse = reverseCameraResponse; m_ExcludedStars = excludedStars; m_SaturatedFlags = saturatedFlags; m_ProfileFittedAmplitudes = profileFittedAmplitudes; m_Sigma = 0; for (int i = 0; i < intencities.Count; i++) { double computed = a * -2.5 * Math.Log10(intencities[i]) + b * colours[i] + c; double diff = Math.Abs(computed - magnitudes[i]); m_Residuals.Add(diff); m_Sigma += diff*diff; } m_Sigma = Math.Sqrt(m_Sigma / (m_Residuals.Count - 1)); m_Filter = filter; m_EmpericalFWHM = empericalFWHM; m_PhotometryReductionMethod = photometryReductionMethod; m_PhotometryBackgroundMethod = photometryBackgroundMethod; m_PsfQuadrature = psfQuadrature; m_PsfFittingMethod = psfFittingMethod; m_A = a; m_B = b; m_C = c; m_Measurer = measurer.Clone(); m_MeasurementAperture = aperture; m_Sigma = 0; m_MinRes = double.MaxValue; m_MaxRes = double.MinValue; m_MinMag = double.MaxValue; m_MaxMag = double.MinValue; for (int i = 0; i < m_Residuals.Count; i++) { double res = m_Residuals[i]; m_Sigma += res * res; if (m_MinRes > res) m_MinRes = res; if (m_MaxRes < res) m_MaxRes = res; double mag = m_Magnitudes[i]; if (m_MinMag > mag) m_MinMag = mag; if (m_MaxMag < mag) m_MaxMag = mag; } m_Sigma = Math.Sqrt(m_Sigma / m_Residuals.Count); }
public Bitmap ResolveObjects( TangraConfig.PhotometryReductionMethod photometryReductionMethod, TangraConfig.PsfQuadrature psfQuadrature, TangraConfig.PsfFittingMethod psfFittingMethod, TangraConfig.BackgroundMethod backgroundMethod, TangraConfig.PreProcessingFilter filter, Guid magnitudeBandId, Rectangle osdRectangleToExclude, Rectangle rectToInclude, bool limitByInclusion, IAstrometrySettings astrometrySettings, ObjectResolverSettings objectResolverSettings) { m_AstrometrySettings = astrometrySettings; StarMap starMap = new StarMap( astrometrySettings.PyramidRemoveNonStellarObject, astrometrySettings.MinReferenceStarFWHM, astrometrySettings.MaxReferenceStarFWHM, astrometrySettings.MaximumPSFElongation, astrometrySettings.LimitReferenceStarDetection); starMap.FindBestMap(StarMapInternalConfig.Default, m_Image, osdRectangleToExclude, rectToInclude, limitByInclusion); float r0 = 0; m_MagnitudeFit = StarMagnitudeFit.PerformFit( m_AstrometryController, m_VideoController, m_Image.Pixelmap.BitPixCamera, m_Image.Pixelmap.MaxSignalValue, m_Astrometry.FitInfo, photometryReductionMethod, psfQuadrature, psfFittingMethod, backgroundMethod, filter, m_Stars, magnitudeBandId, 1.0f, TangraConfig.KnownCameraResponse.Undefined, null, null, null, ref r0); m_BackgroundFlux = m_MagnitudeFit.GetBackgroundIntencity(); m_BackgroundMag = m_MagnitudeFit.GetMagnitudeForIntencity(m_BackgroundFlux); if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose()) { Trace.WriteLine(string.Format("Plate FWHM: {0}", 2 * Math.Sqrt(Math.Log(2)) * r0)); } PeakPixelResolver resolver = new PeakPixelResolver(m_Image); resolver.ResolvePeakPixels(osdRectangleToExclude, rectToInclude, limitByInclusion, objectResolverSettings.ExcludeEdgeAreaPixels, objectResolverSettings.MinDistanceBetweenPeakPixels); List <double> identifiedMagnitudes = new List <double>(); List <double> identifiedR0s = new List <double>(); m_IdentifiedObjects.Clear(); m_UidentifiedObjects.Clear(); foreach (KeyValuePair <int, int> peakPixel in resolver.PeakPixels.Keys) { int x = peakPixel.Key; int y = peakPixel.Value; bool isSaturated; double intencity = m_MagnitudeFit.GetIntencity(new ImagePixel(255, x, y), out isSaturated); double magnitude = m_MagnitudeFit.GetMagnitudeForIntencity(intencity); if (magnitude < m_MaxMagForAstrometry) { double RADeg, DEDeg; PSFFit fit; starMap.GetPSFFit(x, y, PSFFittingMethod.NonLinearFit, out fit); if (fit.IMax < 0) { continue; } if (fit.IMax < fit.I0) { continue; } if (fit.Certainty < objectResolverSettings.MinCertainty) { continue; } if (fit.FWHM < objectResolverSettings.MinFWHM) { continue; } if (fit.IMax - fit.I0 < objectResolverSettings.MinAmplitude) { continue; } m_Astrometry.GetRADEFromImageCoords(fit.XCenter, fit.YCenter, out RADeg, out DEDeg); // All stars closer than 2 arcsec to this position List <IStar> matchingStars = m_Stars.Where(s => Math.Abs(AngleUtility.Elongation(s.RADeg, s.DEDeg, RADeg, DEDeg) * 3600.0) < objectResolverSettings.MaxStarMatchMagDif).ToList(); bool identified = false; if (matchingStars.Count >= 1) { foreach (IStar star in matchingStars) { if (objectResolverSettings.MaxStarMatchMagDif >= Math.Abs(magnitude - star.Mag)) { // The star is identified. Do we care more? if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose()) { Trace.WriteLine(string.Format("STAR ({0}, {1}) No -> {2}; Mag -> {3} (Expected: {4}); R0 = {5}", x, y, star.StarNo, magnitude.ToString("0.00"), star.Mag.ToString("0.00"), fit.R0.ToString("0.0"))); } identifiedMagnitudes.Add(magnitude); identifiedR0s.Add(fit.R0); m_IdentifiedObjects.Add(fit, star); identified = true; break; } } } if (matchingStars.Count == 0 || !identified) { // The object is not in the star database // TODO: Test for hot pixel. Match to hot pixel profile from the brightest pixel in the area m_UidentifiedObjects.Add(fit, magnitude); } } else { // Don't bother with too faint objects } } if (m_IdentifiedObjects.Count > 0) { double mean = identifiedR0s.Average(); double variance = 0; foreach (double rr0 in identifiedR0s) { variance += (rr0 - mean) * (rr0 - mean); } variance = Math.Sqrt(variance / (m_IdentifiedObjects.Count - 1)); double minR0 = mean - variance; double maxR0 = mean + variance; identifiedMagnitudes.Sort(); double maxStarMag = identifiedMagnitudes[Math.Max(0, (int)Math.Truncate(0.9 * identifiedMagnitudes.Count))]; if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose()) { Trace.WriteLine(string.Format("Max Star Mag: {0}; R0 ({1}, {2})", maxStarMag.ToString("0.00"), minR0.ToString("0.0"), maxR0.ToString("0.0"))); } // NOTE: The R0 exclusion may ignore bright comets ! m_UnknownObjects = m_UidentifiedObjects .Where(p => p.Value < maxStarMag && p.Key.R0 >= minR0 && p.Key.R0 <= maxR0) .ToDictionary(p => p.Key, p => p.Value); if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose()) { foreach (PSFFit obj in m_UnknownObjects.Keys) { Trace.WriteLine(string.Format("UNK: ({0}, {1}) Mag -> {2}; R0 = {3}", obj.XCenter.ToString("0.0"), obj.YCenter.ToString("0.0"), m_UnknownObjects[obj].ToString("0.00"), obj.R0.ToString("0.0"))); } } } Bitmap bitmap = m_Image.Pixelmap.CreateDisplayBitmapDoNotDispose(); using (Graphics g = Graphics.FromImage(bitmap)) { foreach (PSFFit star in m_IdentifiedObjects.Keys) { float x = (float)star.XCenter; float y = (float)star.YCenter; g.DrawEllipse(Pens.GreenYellow, x - 5, y - 5, 10, 10); } foreach (PSFFit star in m_UnknownObjects.Keys) { float x = (float)star.XCenter; float y = (float)star.YCenter; g.DrawEllipse(Pens.Tomato, x - 8, y - 8, 16, 16); } g.Save(); } return(bitmap); }
public StarMagnitudeFit( AstroImage astroImage, int bitPix, List <double> intencities, List <double> magnitudes, List <double> colours, List <IStar> starNumbers, List <PSFFit> psfGaussians, List <double> profileFittedAmplitudes, List <bool> saturatedFlags, double a, double b, double c, float encodingGamma, TangraConfig.KnownCameraResponse reverseCameraResponse, int excludedStars, TangraConfig.PreProcessingFilter filter, double empericalFWHM, TangraConfig.PhotometryReductionMethod photometryReductionMethod, TangraConfig.BackgroundMethod photometryBackgroundMethod, TangraConfig.PsfQuadrature psfQuadrature, TangraConfig.PsfFittingMethod psfFittingMethod, MeasurementsHelper measurer, float?aperture) { m_CurrentAstroImage = astroImage; m_BitPix = bitPix; m_Intencities = intencities; m_Magnitudes = magnitudes; m_Colours = colours; m_Residuals = new List <double>(); m_StarNumbers = starNumbers; m_PSFGaussians = psfGaussians; m_EncodingGamma = encodingGamma; m_ReverseCameraResponse = reverseCameraResponse; m_ExcludedStars = excludedStars; m_SaturatedFlags = saturatedFlags; m_ProfileFittedAmplitudes = profileFittedAmplitudes; m_Sigma = 0; for (int i = 0; i < intencities.Count; i++) { double computed = a * -2.5 * Math.Log10(intencities[i]) + b * colours[i] + c; double diff = Math.Abs(computed - magnitudes[i]); m_Residuals.Add(diff); m_Sigma += diff * diff; } m_Sigma = Math.Sqrt(m_Sigma / (m_Residuals.Count - 1)); m_Filter = filter; m_EmpericalFWHM = empericalFWHM; m_PhotometryReductionMethod = photometryReductionMethod; m_PhotometryBackgroundMethod = photometryBackgroundMethod; m_PsfQuadrature = psfQuadrature; m_PsfFittingMethod = psfFittingMethod; m_A = a; m_B = b; m_C = c; m_Measurer = measurer.Clone(); m_MeasurementAperture = aperture; m_Sigma = 0; m_MinRes = double.MaxValue; m_MaxRes = double.MinValue; m_MinMag = double.MaxValue; m_MaxMag = double.MinValue; for (int i = 0; i < m_Residuals.Count; i++) { double res = m_Residuals[i]; m_Sigma += res * res; if (m_MinRes > res) { m_MinRes = res; } if (m_MaxRes < res) { m_MaxRes = res; } double mag = m_Magnitudes[i]; if (m_MinMag > mag) { m_MinMag = mag; } if (m_MaxMag < mag) { m_MaxMag = mag; } } m_Sigma = Math.Sqrt(m_Sigma / m_Residuals.Count); }
public static StarMagnitudeFit PerformFit( IAstrometryController astrometryController, IVideoController videoController, int bitPix, uint maxSignalValue, FitInfo astrometricFit, TangraConfig.PhotometryReductionMethod photometryReductionMethod, TangraConfig.PsfQuadrature psfQuadrature, TangraConfig.PsfFittingMethod psfFittingMethod, TangraConfig.BackgroundMethod photometryBackgroundMethod, TangraConfig.PreProcessingFilter filter, List <IStar> catalogueStars, Guid magnitudeBandId, float encodingGamma, TangraConfig.KnownCameraResponse reverseCameraResponse, float?aperture, float?annulusInnerRadius, int?annulusMinPixels, ref float empericalPSFR0) { uint saturatedValue = TangraConfig.Settings.Photometry.Saturation.GetSaturationForBpp(bitPix, maxSignalValue); MeasurementsHelper measurer = new MeasurementsHelper( bitPix, photometryBackgroundMethod, TangraConfig.Settings.Photometry.SubPixelSquareSize, saturatedValue); measurer.SetCoreProperties( annulusInnerRadius ?? TangraConfig.Settings.Photometry.AnnulusInnerRadius, annulusMinPixels ?? TangraConfig.Settings.Photometry.AnnulusMinPixels, CorePhotometrySettings.Default.RejectionBackgroundPixelsStdDev, 2 /* TODO: This must be configurable */); var bgProvider = new BackgroundProvider(videoController); measurer.GetImagePixelsCallback += new MeasurementsHelper.GetImagePixelsDelegate(bgProvider.measurer_GetImagePixelsCallback); List <double> intencities = new List <double>(); List <double> magnitudes = new List <double>(); List <double> colours = new List <double>(); List <double> residuals = new List <double>(); List <bool> saturatedFlags = new List <bool>(); List <IStar> stars = new List <IStar>(); List <PSFFit> gaussians = new List <PSFFit>(); List <MagFitRecord> fitRecords = new List <MagFitRecord>(); AstroImage currentAstroImage = videoController.GetCurrentAstroImage(false); Rectangle osdRectToExclude = astrometryController.OSDRectToExclude; Rectangle rectToInclude = astrometryController.RectToInclude; bool limitByInclusion = astrometryController.LimitByInclusion; int matSize = CorePhotometrySettings.Default.MatrixSizeForCalibratedPhotometry; double a = double.NaN; double b = double.NaN; double c = double.NaN; int excludedStars = 0; double empericalFWHM = double.NaN; try { foreach (PlateConstStarPair pair in astrometricFit.AllStarPairs) { if (limitByInclusion && !rectToInclude.Contains((int)pair.x, (int)pair.y)) { continue; } if (!limitByInclusion && osdRectToExclude.Contains((int)pair.x, (int)pair.y)) { continue; } IStar star = catalogueStars.Find(s => s.StarNo == pair.StarNo); if (star == null || double.IsNaN(star.Mag) || star.Mag == 0) { continue; } uint[,] data = currentAstroImage.GetMeasurableAreaPixels((int)pair.x, (int)pair.y, matSize); PSFFit fit = new PSFFit((int)pair.x, (int)pair.y); fit.Fit(data, PSF_FIT_AREA_SIZE); if (!fit.IsSolved) { continue; } MagFitRecord record = new MagFitRecord(); record.Star = star; record.Pair = pair; record.PsfFit = fit; record.Saturation = IsSaturated(data, matSize, saturatedValue); if (!EXCLUDE_SATURATED_STARS || !record.Saturation) { fitRecords.Add(record); } } // We need the average R0 if it hasn't been determined yet if (float.IsNaN(empericalPSFR0)) { empericalPSFR0 = 0; foreach (MagFitRecord rec in fitRecords) { empericalPSFR0 += (float)rec.PsfFit.R0; } empericalPSFR0 /= fitRecords.Count; } empericalFWHM = 2 * Math.Sqrt(Math.Log(2)) * empericalPSFR0; foreach (MagFitRecord record in fitRecords) { ImagePixel center = new ImagePixel(255, record.Pair.x, record.Pair.y); int areaSize = filter == TangraConfig.PreProcessingFilter.NoFilter ? 17 : 19; int centerX = (int)Math.Round(center.XDouble); int centerY = (int)Math.Round(center.YDouble); uint[,] data = currentAstroImage.GetMeasurableAreaPixels(centerX, centerY, areaSize); uint[,] backgroundPixels = currentAstroImage.GetMeasurableAreaPixels(centerX, centerY, 35); measurer.MeasureObject( center, data, backgroundPixels, currentAstroImage.Pixelmap.BitPixCamera, filter, photometryReductionMethod, psfQuadrature, psfFittingMethod, aperture != null ? aperture.Value : (float)Aperture(record.PsfFit.FWHM), record.PsfFit.FWHM, (float)empericalFWHM, new FakeIMeasuredObject(record.PsfFit), null, null, false); double intensity = measurer.TotalReading - measurer.TotalBackground; if (intensity > 0) { var mag = record.Star.GetMagnitudeForBand(magnitudeBandId); var clr = record.Star.MagJ - record.Star.MagK; if (!double.IsNaN(mag) && !double.IsNaN(clr) && !double.IsInfinity(mag) && !double.IsInfinity(clr)) { intencities.Add(intensity); magnitudes.Add(record.Star.GetMagnitudeForBand(magnitudeBandId)); colours.Add(record.Star.MagJ - record.Star.MagK); gaussians.Add(record.PsfFit); stars.Add(record.Star); saturatedFlags.Add(measurer.HasSaturatedPixels || record.PsfFit.IMax >= measurer.SaturationValue); } } } // Remove stars with unusual PSF fit radii (once only) double sum = 0; for (int i = 0; i < gaussians.Count; i++) { sum += gaussians[i].R0; } double averageR = sum / gaussians.Count; residuals.Clear(); sum = 0; for (int i = 0; i < gaussians.Count; i++) { residuals.Add(averageR - gaussians[i].R0); sum += (averageR - gaussians[i].R0) * (averageR - gaussians[i].R0); } double stdDev = Math.Sqrt(sum) / gaussians.Count; if (EXCLUDE_BAD_RESIDUALS) { for (int i = residuals.Count - 1; i >= 0; i--) { if (Math.Abs(residuals[i]) > 6 * stdDev) { intencities.RemoveAt(i); magnitudes.RemoveAt(i); colours.RemoveAt(i); stars.RemoveAt(i); gaussians.RemoveAt(i); saturatedFlags.RemoveAt(i); } } } double maxResidual = Math.Max(0.1, TangraConfig.Settings.Photometry.MaxResidualStellarMags); for (int itter = 1; itter <= MAX_ITERR; itter++) { residuals.Clear(); SafeMatrix A = new SafeMatrix(intencities.Count, 3); SafeMatrix X = new SafeMatrix(intencities.Count, 1); int idx = 0; for (int i = 0; i < intencities.Count; i++) { A[idx, 0] = magnitudes[i]; A[idx, 1] = colours[i]; A[idx, 2] = 1; X[idx, 0] = -2.5 * Math.Log10(intencities[i]); idx++; } SafeMatrix a_T = A.Transpose(); SafeMatrix aa = a_T * A; SafeMatrix aa_inv = aa.Inverse(); SafeMatrix bx = (aa_inv * a_T) * X; double Ka = bx[0, 0]; double Kb = bx[1, 0]; double Kc = bx[2, 0]; // -2.5 * a * Log(Median-Intensity) = A * Mv + B * Mjk + C - b // -2.5 * Log(Median-Intensity) = Ka * Mv + Kb * Mjk + Kc // Mv = -2.5 * a * Log(Median-Intensity) - b * Mjk - c a = 1 / Ka; b = -Kb / Ka; c = -Kc / Ka; int starsExcludedThisTime = 0; if (EXCLUDE_BAD_RESIDUALS) { List <int> indexesToRemove = new List <int>(); for (int i = 0; i < intencities.Count; i++) { double computed = a * -2.5 * Math.Log10(intencities[i]) + b * colours[i] + c; double diff = Math.Abs(computed - magnitudes[i]); if (itter < MAX_ITERR) { if (Math.Abs(diff) > maxResidual) { indexesToRemove.Add(i); } } else { residuals.Add(diff); } } for (int i = indexesToRemove.Count - 1; i >= 0; i--) { int idxToRemove = indexesToRemove[i]; intencities.RemoveAt(idxToRemove); magnitudes.RemoveAt(idxToRemove); colours.RemoveAt(idxToRemove); stars.RemoveAt(idxToRemove); gaussians.RemoveAt(idxToRemove); saturatedFlags.RemoveAt(idxToRemove); excludedStars++; starsExcludedThisTime++; } } if (starsExcludedThisTime == 0) { break; } } } catch (Exception ex) { Trace.WriteLine(ex.ToString()); } return(new StarMagnitudeFit( currentAstroImage, bitPix, intencities, magnitudes, colours, stars, gaussians, new List <double>(), saturatedFlags, a, b, c, encodingGamma, reverseCameraResponse, excludedStars, filter, empericalFWHM, photometryReductionMethod, photometryBackgroundMethod, psfQuadrature, psfFittingMethod, measurer, aperture)); }
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"); } }