Exemplo n.º 1
0
 public static void RegisterSolutionToImprove(SolutionImprovementEntry improvementEntry)
 {
     lock (s_SyncLock)
     {
         s_ImprovementEntries.Add(improvementEntry);
     }
 }
Exemplo n.º 2
0
		private bool ImproveAndRetestSolution(int i, int j, int k, bool fromPreviousFit = false)
		{
			if (m_Solution != null)
			{
				LeastSquareFittedAstrometry fit = m_Solution as LeastSquareFittedAstrometry;

				if (fit != null)
				{
#if ASTROMETRY_DEBUG
                    SolutionImprovementEntry improvementLog = new SolutionImprovementEntry(fit, i, j, k);
					AstrometricFitDebugger.RegisterSolutionToImprove(improvementLog);
#endif
					ImproveSolution(fit, 1, i, j, k);

				    if (m_ImprovedSolution != null && CorePyramidConfig.Default.AttempDoubleSolutionImprovement)
				    {
                        if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceInfo())
                            Trace.WriteLine("Attempting double solution improvement.");

				        ImproveSolution(m_ImprovedSolution, 2, i, j, k);
				    }

					if (m_ImprovedSolution == null)
					{
#if ASTROMETRY_DEBUG
						improvementLog.Fail(SolutionImprovementFailureReason.FailedToImproveSolution);
#endif
                        if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose())
						    Trace.WriteLine("Failing potential fit because the improved solultion is NULL.");
					
						// Check for a false negative
						double? deltaArcSec = null;

						if (!double.IsNaN(DebugResolvedRA0Deg) && !double.IsNaN(DebugResolvedDE0Deg))
						{
							deltaArcSec = AngleUtility.Elongation(
								fit.RA0Deg,
								fit.DE0Deg,
								DebugResolvedRA0Deg,
								DebugResolvedDE0Deg) * 3600;

							double deltaPixels = m_PlateConfig.GetDistanceInPixels(deltaArcSec.Value);

							if (deltaPixels < 5)
							{
                                if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose())
								    Trace.WriteLine(string.Format("DEBUG ALIGN: False negative alignment on {0}-{1}-{2}", i, j, k));

								Trace.Assert(false, "False Negative!");
								SaveAlignImage(fit.FitInfo.AllStarPairs, i, j, k, false);
								return false;
							}
						}

						return false;
					}					

#if ASTROMETRY_DEBUG
					improvementLog.ImprovedSolution = m_ImprovedSolution;
#endif
					List<PlateConstStarPair> allPairsInTheFrame =
						m_ImprovedSolution.FitInfo.AllStarPairs
							.Where(p => p.x > 0 && p.x < m_PlateConfig.ImageWidth && p.y > 0 && p.y < m_PlateConfig.ImageHeight)
							.ToList();

					if (allPairsInTheFrame.Count < 4)
					{
#if ASTROMETRY_DEBUG
						improvementLog.Fail(SolutionImprovementFailureReason.LessThanFourStars);
#endif
                        LogUnsuccessfulFitImage(m_ImprovedSolution, i, j, k, 
                            "Failing potential fit because there are less than 4 included stars in the improved solultion .");

						return false;
					}

					double detectionLimit = m_Settings.DetectionLimit;					
					int uncertainStars = allPairsInTheFrame.Count(p => p.DetectionCertainty < detectionLimit);

					if (allPairsInTheFrame.Count - uncertainStars < uncertainStars)
					{
						// Cant be right!
#if ASTROMETRY_DEBUG
						improvementLog.Fail(SolutionImprovementFailureReason.TooManyUncertainStars);
#endif
                        LogUnsuccessfulFitImage(m_ImprovedSolution, i, j, k, 
                            string.Format("Failing potential fit because there are {0} out of {1} uncertain stars in the improved solution.", uncertainStars, allPairsInTheFrame.Count));

						return false;
					}

					int excludedStars = allPairsInTheFrame.Count(p => p.FitInfo.ExcludedForHighResidual);
					if (allPairsInTheFrame.Count - excludedStars < 20 && allPairsInTheFrame.Count - excludedStars < excludedStars)
					{
						// Cant be right!
#if ASTROMETRY_DEBUG
						improvementLog.Fail(SolutionImprovementFailureReason.TooManyExcludedStars);
#endif
                        LogUnsuccessfulFitImage(m_ImprovedSolution, i, j, k, 
                            string.Format("Failing potential fit because there are {0} out of {1} excluded stars in the improved solultion.", excludedStars, allPairsInTheFrame.Count));

						return false;
					}

					List<double> residuls = allPairsInTheFrame
						.Select(p => p.FitInfo.ResidualArcSec)
						.OrderByDescending(r => r).ToList();

					double averageResidual = residuls.Average();

					if (averageResidual >
						CorePyramidConfig.Default.MaxMeanResidualInPixelsInSuccessfulFit * m_PlateConfig.GetDistanceInArcSec(0, 0, 1, 1))
					{
#if ASTROMETRY_DEBUG
						improvementLog.Fail(SolutionImprovementFailureReason.MaxCoreMeanResidualTooHigh);
#endif
                        LogUnsuccessfulFitImage(m_ImprovedSolution, i, j, k, 
                            string.Format("Failing potential fit because the average residual of {0}\" is larger than {1} px", averageResidual.ToString("0.00"), CorePyramidConfig.Default.MaxMeanResidualInPixelsInSuccessfulFit.ToString("0.0")));

						return false;						
					}

					if (m_DetermineAutoLimitMagnitude && double.IsNaN(m_DetectedLimitingMagnitude))
					{
						List<PlateConstStarPair> sortedPairs = m_ImprovedSolution.FitInfo.AllStarPairs
						.Where(p => p.DetectionCertainty >= m_Settings.LimitReferenceStarDetection)
						.ToList();

						List<ulong> starNosUnderDetectionLimit = m_ImprovedSolution.FitInfo.AllStarPairs
						.Where(p => p.DetectionCertainty < m_Settings.LimitReferenceStarDetection)
						.Select(p => p.StarNo)
						.ToList();

						m_ImprovedSolution.FitInfo.AllStarPairs
							.RemoveAll(p => p.DetectionCertainty < m_Settings.LimitReferenceStarDetection);

						sortedPairs.Sort((a, b) => a.DetectionCertainty.CompareTo(b.DetectionCertainty));

						double limitingMag = GetLimitingMagnitudeFromSortedPairs(sortedPairs) + 0.01;					
						if (!double.IsNaN(limitingMag))
						{
							m_ImprovedSolution.FitInfo.DetectedLimitingMagnitude = limitingMag;

							m_DetectedLimitingMagnitude = m_ImprovedSolution.FitInfo.DetectedLimitingMagnitude;
							m_CelestialPyramidStars = m_CelestialAllStars
								.Where(s => s.Mag <= m_DetectedLimitingMagnitude && !starNosUnderDetectionLimit.Contains(s.StarNo))
								.ToList();

							// Also reduce all stars. This would mean if the integration changes on the way, the user will
							// need to start the astrometry again
							m_CelestialAllStars = m_CelestialPyramidStars;

							m_ImprovedSolution.FitInfo.AllStarPairs.RemoveAll(p => !p.FitInfo.UsedInSolution || p.Mag > limitingMag);
							allPairsInTheFrame.RemoveAll(p => !p.FitInfo.UsedInSolution || p.Mag > limitingMag || p.DetectionCertainty < m_Settings.LimitReferenceStarDetection);
						
							InitializePyramidMatching();

                            if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose())
							    Trace.WriteLine(string.Format("Limiting reference star magnitude estimated as {0:0.0}", limitingMag));
						}
					}
					else if (m_DetermineAutoLimitMagnitude)
					{
						m_ImprovedSolution.FitInfo.DetectedLimitingMagnitude = m_DetectedLimitingMagnitude;
					}

					if (m_ImprovedSolution.FitInfo.AllStarPairs.Count > m_Settings.MaximumNumberOfStars)
					{
						m_ImprovedSolution.FitInfo.AllStarPairs.Sort((a, b) => a.Mag.CompareTo(b.Mag));

						List<PlateConstStarPair> usedPairs = m_ImprovedSolution.FitInfo.AllStarPairs.Where(p => p.FitInfo.UsedInSolution).ToList();
						if (usedPairs.Count > m_Settings.MaximumNumberOfStars)
						{
							double maxMagToInclude = usedPairs[m_Settings.MaximumNumberOfStars - 1].Mag - 0.01;

							m_ImprovedSolution.FitInfo.AllStarPairs.RemoveAll(p => p.Mag > maxMagToInclude);
							allPairsInTheFrame.RemoveAll(p => p.Mag > maxMagToInclude);

							if (m_DetermineAutoLimitMagnitude)
							{
								// This will remove all grayed circles of the excess stars which have been excluded 
								m_CelestialPyramidStars.RemoveAll(p => p.Mag > maxMagToInclude);
								m_CelestialAllStars = m_CelestialPyramidStars;
								
								InitializePyramidMatching();
							}
						}
                    }

                    #region Check how many of the considered stars, brighter than the detected limiting magnitude were not used in the solution
                    int detectedStars = 0;
                    int consideredStars = 0;
                    int missingStars = 0;
                    double checkMag = ImprovedSolutionIncludedMaxMag;
				    
                    double minDetectionCertaintyUsedInSolution = m_ImprovedSolution.FitInfo.AllStarPairs.Where(x => x.FitInfo.UsedInSolution).Min(x => x.DetectionCertainty);
				    if (TangraConfig.Settings.Astrometry.DetectionLimit < minDetectionCertaintyUsedInSolution)
				        minDetectionCertaintyUsedInSolution = TangraConfig.Settings.Astrometry.DetectionLimit;

				    foreach (IStar catStar in ConsideredStars)
				    {
                        double x, y;
				        m_ImprovedSolution.GetImageCoordsFromRADE(catStar.RADeg, catStar.DEDeg, out x, out y);
				        if (x > 0 && y > 0 && x < m_PlateConfig.ImageWidth && y < m_PlateConfig.ImageHeight)
				        {
				            if (catStar.Mag < checkMag)
				            {
				                if (m_StarMap.GetFeatureInRadius((int) x, (int) y, 2) == null)
				                {
                                    // Brighter star not in the solition. Is there actually a star there
                                    PSFFit psfFit;
                                    m_StarMap.GetPSFFit((int)x, (int)y, PSFFittingMethod.NonLinearFit, out psfFit);

				                    if (psfFit != null && psfFit.IsSolved &&
				                        psfFit.Certainty > minDetectionCertaintyUsedInSolution)
				                    {
				                        consideredStars++;
				                    }
				                    else
				                        missingStars++;
				                }
                                else
				                    consideredStars++;

				                if (m_ImprovedSolution.FitInfo.AllStarPairs.FirstOrDefault(s => s.StarNo == catStar.StarNo) != null)
				                    detectedStars++;
				            }
				        }
				    }
                    if (detectedStars < 25 && !fromPreviousFit)
				    {
				        if (missingStars > detectedStars || missingStars > consideredStars/2)
				        {
                            LogUnsuccessfulFitImage(fit, i, j, k,
                                string.Format("Failing potential fit because {0} missing stars are more than {1} detected stars OR they are more than half of the {2} considered stars.", missingStars, detectedStars, consideredStars));
				            return false;
				        }

				        double detectedConsideredStarsPercentage = 1.0 * detectedStars/(consideredStars + missingStars);

				        if (detectedConsideredStarsPercentage < 0.50 && consideredStars > 2 * detectedStars)
				        {
                            LogUnsuccessfulFitImage(m_ImprovedSolution, i, j, k, 
                                string.Format("Failing potential fit because the {0} detected considered stars are less than 50% and {1} considered stars are more than double the {2} detected stars.", detectedConsideredStarsPercentage, consideredStars, detectedStars));

				            return false;
				        }
				        if (detectedConsideredStarsPercentage < 0.25 && consideredStars > 10)
				        {
                            LogUnsuccessfulFitImage(m_ImprovedSolution, i, j, k, 
                                string.Format("Failing potential fit because the {0}% of detected considered stars are less than 25% and {1} considered stars are more than 10.", detectedConsideredStarsPercentage, consideredStars));

				            return false;
				        }
                    }
                    #endregion

                    if (DebugResolvedStars != null)
					{
						DebugTripple tripple = m_DebugTripples.FirstOrDefault(t =>
							(t.Id1 == i && t.Id2 == j && t.Id3 == k) ||
							(t.Id1 == i && t.Id2 == k && t.Id3 == j) ||
							(t.Id1 == j && t.Id2 == i && t.Id3 == k) ||
							(t.Id1 == j && t.Id2 == k && t.Id3 == i) ||
							(t.Id1 == k && t.Id2 == i && t.Id3 == j) ||
							(t.Id1 == k && t.Id2 == j && t.Id3 == i));

						if (tripple != null)
						{
							double? deltaArcSec = null;

							if (!double.IsNaN(DebugResolvedRA0Deg) && !double.IsNaN(DebugResolvedDE0Deg))
							{
								deltaArcSec = AngleUtility.Elongation(
									m_ImprovedSolution.RA0Deg, 
									m_ImprovedSolution.DE0Deg, 
									DebugResolvedRA0Deg, 
									DebugResolvedDE0Deg) * 3600;

								double deltaPixels = m_PlateConfig.GetDistanceInPixels(deltaArcSec.Value);

								if (deltaPixels > 1)
								{
									Trace.Assert(false, "False Positive!");
                                    if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose())
									    Trace.WriteLine(string.Format("DEBUG ALIGN: False positive alignment on {0}-{1}-{2}", i, j, k));
									return false;
								}
							}

                            if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose())
							    Trace.WriteLine(string.Format(
								    "DEBUG ALIGN: Successful alignment on {0}-{1}-{2}{4}. Remaining combinations: {3}",
								    i, j, k, m_DebugTripples.Count,
								    deltaArcSec.HasValue ? string.Format(" ({0:0.000}mas Diff)", 1000 * deltaArcSec.Value) : ""));

							m_DebugTripples.Remove(tripple);

							if (DebugSaveAlignImages)
								SaveAlignImage(m_ImprovedSolution.FitInfo.AllStarPairs, i, j, k, true);

							return m_DebugTripples.Count == 0;
						}
						else
						{
                            LogUnsuccessfulFitImage(fit, i, j, k, 
                                string.Format("DEBUG ALIGN: Unexpected alignment on {0}-{1}-{2}", i, j, k));

							return false;
						}
					}
					return true;					
				}
			}

            if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose())
			    Trace.WriteLine("Failing potential fit because there is no solution or it hasn't been fitted using least squares.");

			return false;
		}
Exemplo n.º 3
0
 public static void RegisterSolutionToImprove(SolutionImprovementEntry improvementEntry)
 {
     lock(s_SyncLock)
     {
         s_ImprovementEntries.Add(improvementEntry);
     }
 }