public PerformMatchResult PerformMatch(out LeastSquareFittedAstrometry improvedSolution) { LeastSquareFittedAstrometry distanceBasedSolution; PlateConstantsSolver solver; return(PerformMatch(out distanceBasedSolution, out improvedSolution, out solver)); }
internal SolutionImprovementEntry(LeastSquareFittedAstrometry fit, int i, int j, int k) { FitToImprove = fit; this.i = i; this.j = j; this.k = k; }
internal SolutionImprovementEntry(LeastSquareFittedAstrometry fit, int i, int j, int k) { FitToImprove = fit; this.i = i; this.j = j; this.k = k; }
public override void MouseClick(ObjectClickEventArgs e) { if (m_State == FittingsState.Configuring) { m_OSDExcluderTool.MouseClick(e); } if (m_State == FittingsState.Solved) { IStarMap starMap = AstrometryContext.Current.StarMap; if (starMap != null) { int x, y; StarMapFeature feature = starMap.GetFeatureInRadius(e.Pixel.X, e.Pixel.Y, 5); if (feature != null) { x = feature.GetCenter().X; y = feature.GetCenter().Y; } else { x = e.Pixel.X; y = e.Pixel.Y; } int searchArea = Control.ModifierKeys == Keys.Shift ? 5 : 10; PSFFit psfFit; ImagePixel pixelCent = starMap.GetPSFFit(x, y, searchArea, out psfFit); if (pixelCent != null && pixelCent != ImagePixel.Unspecified) { PlateConstStarPair selectedPair = null; LeastSquareFittedAstrometry astrometry = FittedAstrometryFromUserSelectedFitGrade(); if (astrometry != null) { foreach (PlateConstStarPair pair in astrometry.FitInfo.AllStarPairs) { if (Math.Abs(pair.x - pixelCent.X) < 2 && Math.Abs(pair.y - pixelCent.Y) < 2) { selectedPair = pair; break; } } } DrawHighResFeature(pixelCent, selectedPair, astrometry); } else { ClearZoomImage(); } } } }
/// <summary> /// Does the second step of the plate calibration: Least Square with the mapped celestrial stars (from step 1) /// </summary> /// <param name="fitOrder"></param> /// <returns></returns> public bool SolvePlateConstantsPhase2(FitOrder fitOrder, bool fineFit) { LeastSquareFittedAstrometry firstSolution; m_SolvedPlate = m_ConstantsSolver.SolveWithLinearRegression(m_AstrometrySettings, out firstSolution); if (firstSolution != null) { if (fineFit) { m_Context.InitialSecondAstrometricFit = LeastSquareFittedAstrometry.FromReflectedObject(firstSolution); m_Context.InitialSecondAstrometricFit.FitInfo.AllStarPairs.AddRange(firstSolution.FitInfo.AllStarPairs); } else { m_Context.InitialFirstAstrometricFit = LeastSquareFittedAstrometry.FromReflectedObject(firstSolution); m_Context.InitialFirstAstrometricFit.FitInfo.AllStarPairs.AddRange(firstSolution.FitInfo.AllStarPairs); } } if (m_SolvedPlate != null) { // TODO: Make this configurable if (m_ConstantsSolver.ExcludedForBadResidualsCount < 2 * m_ConstantsSolver.IncludedInSolutionCount) { LeastSquareFittedAstrometry lsfa = m_SolvedPlate as LeastSquareFittedAstrometry; // At least 33% of the stars should be included in the solution if (fineFit) { m_Context.SecondAstrometricFit = lsfa; } else { m_Context.FirstAstrometricFit = LeastSquareFittedAstrometry.FromReflectedObject(lsfa); m_Context.FirstAstrometricFit.FitInfo.AllStarPairs.AddRange(lsfa.FitInfo.AllStarPairs); } #if ASTROMETRY_DEBUG //foreach (PlateConstStarPair pair in lsfa.FitInfo.AllStarPairs) //{ // double x, y; // lsfa.GetImageCoordsFromRADE(pair.RADeg, pair.DEDeg, out x, out y); // double dist = lsfa.GetDistanceInArcSec(x, y, pair.x, pair.y); // Trace.Assert(Math.Abs(dist) < pair.FitInfo.ResidualArcSec*1.1); //} #endif return(true); } } return(false); }
public PlateObjectResolver( IAstrometryController astrometryController, IVideoController videoController, AstroImage image, LeastSquareFittedAstrometry impSol, List <IStar> stars, double maxMagForAstrometry) { m_AstrometryController = astrometryController; m_VideoController = videoController; m_Image = image; m_Astrometry = impSol; m_Stars = stars; m_MaxMagForAstrometry = maxMagForAstrometry; }
public PlateObjectResolver( IAstrometryController astrometryController, IVideoController videoController, AstroImage image, LeastSquareFittedAstrometry impSol, List<IStar> stars, double maxMagForAstrometry) { m_AstrometryController = astrometryController; m_VideoController = videoController; m_Image = image; m_Astrometry = impSol; m_Stars = stars; m_MaxMagForAstrometry = maxMagForAstrometry; }
public void NextFrame(int frameNo, IAstroImage astroImage, IStarMap starMap, LeastSquareFittedAstrometry astrometricFit) { IsTrackedSuccessfully = false; ImagePixel centroid = AstrometryContext.Current.StarMap.GetCentroid( (int)TrackedObject.LastKnownX, (int)TrackedObject.LastKnownY, CoreAstrometrySettings.Default.PreMeasureSearchCentroidRadius); if (centroid != null) { PSFFit psfFit; AstrometryContext.Current.StarMap.GetPSFFit( centroid.X, centroid.Y, PSFFittingMethod.NonLinearFit, out psfFit); if (psfFit != null) { double ra, de; astrometricFit.GetRADEFromImageCoords(psfFit.XCenter, psfFit.YCenter, out ra, out de); double maxPosDiffArcSec = astrometricFit.GetDistanceInArcSec(astrometricFit.Image.CenterXImage, astrometricFit.Image.CenterYImage, astrometricFit.Image.CenterXImage + CoreAstrometrySettings.Default.PreMeasureSearchCentroidRadius, astrometricFit.Image.CenterYImage); if (!double.IsNaN(TrackedObject.RAHours)) { double posDif = 3600 * AngleUtility.Elongation(15 * TrackedObject.RAHours, TrackedObject.DEDeg, ra, de); if (posDif > maxPosDiffArcSec) { // NOTE: Not a valid measurement Trace.WriteLine(string.Format("The target position is too far from the last measured position", posDif)); return; } } TrackedObject.RAHours = ra / 15.0; TrackedObject.DEDeg = de; TrackedObject.LastKnownX = psfFit.XCenter; TrackedObject.LastKnownY = psfFit.YCenter; TrackedObject.PSFFit = psfFit; IsTrackedSuccessfully = true; } } }
protected LeastSquareFittedAstrometry FittedAstrometryFromUserSelectedFitGrade() { LeastSquareFittedAstrometry astrometry = null; switch (m_FitGrade) { case 0: if (m_CalibrationContext.InitialSecondAstrometricFit != null) { astrometry = m_CalibrationContext.InitialSecondAstrometricFit; } else if (m_CalibrationContext.InitialFirstAstrometricFit != null) { astrometry = m_CalibrationContext.InitialFirstAstrometricFit; } break; case 1: astrometry = m_CalibrationContext.FirstAstrometricFit; break; case 2: astrometry = m_CalibrationContext.SecondAstrometricFit; break; case 3: astrometry = m_CalibrationContext.DistanceBasedFit; break; case 4: astrometry = m_CalibrationContext.ImprovedDistanceBasedFit; break; default: astrometry = null; break; } return(astrometry); }
public PerformMatchResult PerformMatch(out LeastSquareFittedAstrometry improvedSolution) { LeastSquareFittedAstrometry distanceBasedSolution; PlateConstantsSolver solver; return PerformMatch(out distanceBasedSolution, out improvedSolution, out solver); }
public PerformMatchResult PerformMatch( out LeastSquareFittedAstrometry distanceBasedSolution, out LeastSquareFittedAstrometry improvedSolution, out PlateConstantsSolver solver) { DistanceBasedContext.FieldAlignmentResult alignmentResult = null; improvedSolution = null; #if UNIT_TESTS Flags.Reset(); #endif m_PerformanceWatch.Reset(); m_PerformanceWatch.Start(); try { if (m_StarMap.FeaturesCount < TangraConfig.Settings.Astrometry.MinimumNumberOfStars) { distanceBasedSolution = null; solver = null; return PerformMatchResult.FieldAlignmentFailed; } if (!m_IsCalibration && m_Solution != null) { // Try using the cache from the last time alignmentResult = Context.DoFieldAlignment(m_StarMap, m_Solution.FitInfo, false); m_Solution = GetSolution(alignmentResult); #if UNIT_TESTS Flags.CacheFromLastTimeAttempted = true; Flags.CacheFromLastTimeSuccessful = m_Solution != null; #endif } if (m_Solution == null && !m_IsCalibration && m_ManualStarMatch != null) { // Try using the manual star match alignmentResult = Context.DoFieldAlignment(m_StarMap, m_ManualStarMatch); m_Solution = GetSolution(alignmentResult); #if UNIT_TESTS Flags.ManualMatchAttempted = true; Flags.ManualMatchSuccessful = m_Solution != null; #endif } if (m_Solution == null && !m_RatioBasedFittedFocalLengthIsDerived && !m_FitSettings.PyramidForceFixedFocalLength && !m_IsCalibration) { m_OperationNotifier.NotifyBeginLongOperation("Performing a plate solve ..."); try { // If this is the first fit, then fit a focal length alignmentResult = Context.DoFieldAlignmentFitFocalLength(m_StarMap); m_Solution = GetSolution(alignmentResult); if (m_Solution != null) { m_RatioBasedFittedFocalLengthIsDerived = true; m_RatioBasedFittedFocalLength = m_Solution.FitInfo.FittedFocalLength; } else { if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceInfo()) Trace.WriteLine("No Solution."); } } finally { m_OperationNotifier.NotifyEndLongOperation(); } #if UNIT_TESTS Flags.RatioBasedFocalLengthFitAttempted = true; Flags.RatioBasedFocalLengthFitSuccessful = m_RatioBasedFittedFocalLengthIsDerived; #endif } else { if (m_Solution == null) { if (m_RatioBasedFittedFocalLengthIsDerived && !m_IsCalibration) { alignmentResult = Context.DoFieldAlignment(m_StarMap, m_RatioBasedFittedFocalLength); m_Solution = GetSolution(alignmentResult); #if UNIT_TESTS Flags.FitWithPreFittedFocalLengthAttempted = true; Flags.FitWithPreFittedFocalLengthSuccessful = m_Solution != null; #endif } else { alignmentResult = Context.DoFieldAlignment(m_StarMap); m_Solution = GetSolution(alignmentResult); #if UNIT_TESTS Flags.FitWithFixedFocalLengthAttempted = true; Flags.FitWithFixedFocalLengthSuccessful = m_Solution != null; #endif } } } m_SearchAborted = Context.m_AbortSearch; if (alignmentResult != null) { distanceBasedSolution = (LeastSquareFittedAstrometry)alignmentResult.Solution; improvedSolution = (LeastSquareFittedAstrometry)alignmentResult.ImprovedSolution; m_Solution = GetSolution(alignmentResult); solver = alignmentResult.Solver; } else { distanceBasedSolution = m_Solution; solver = null; } if (m_SearchAborted) return PerformMatchResult.SearchAborted; #if ASTROMETRY_DEBUG if (m_Solution != null) // No need to keep the debug log any longer when the fit is successful AstrometricFitDebugger.Reset(); #endif if (m_Solution != null) // Clear manually identified starting position in a case of a successful plate solve m_ManualStarMatch = null; return m_Solution != null ? PerformMatchResult.FitSucceessfull : PerformMatchResult.FitImprovementFailed; } finally { // Reset the manually matched stars after every fit attempt m_ManualStarMatch = null; m_PerformanceWatch.Stop(); if (m_Solution != null) { if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceError()) { Trace.WriteLine(string.Format( "Pyramid Match Successful: {0} ms, {1} stars total, aligned on {2} stars, {3} stars matched {4}. Combination: {5}", m_PerformanceWatch.ElapsedMilliseconds, m_CelestialStars.Count, alignmentResult != null ? (alignmentResult.Solution as LeastSquareFittedAstrometry).FitInfo.NumberOfStarsUsedInSolution() : 0, improvedSolution != null ? improvedSolution.FitInfo.NumberOfStarsUsedInSolution().ToString() : "N/A", improvedSolution != null ? string.Format(" ({0}-{1} mag)", Context.ImprovedSolutionIncludedMinMag.ToString("0.00"), Context.ImprovedSolutionIncludedMaxMag.ToString("0.00")) : null, alignmentResult != null ? alignmentResult.MatchedTriangle : null)); } } else { if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceError()) Trace.WriteLine(string.Format("Pyramid Match Failed: {0} ms, {1} stars total, NO MATCH", m_PerformanceWatch.ElapsedMilliseconds, m_CelestialStars.Count)); if (Context.DebugResolvedStars != null) { foreach(DistanceBasedContext.DebugTripple tripple in Context.m_DebugTripples) { if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose()) Trace.WriteLine(string.Format("DEBUG ALIGN: Missed alignment on {0}-{1}-{2}", tripple.Id1, tripple.Id2, tripple.Id3)); } } } #if ASTROMETRY_DEBUG Trace.Assert(!m_DetermineAutoLimitMagnitude || m_Solution == null || m_Solution.FitInfo.DetectedLimitingMagnitude != 0); #endif } }
private void ImproveSolution(LeastSquareFittedAstrometry fit, double coeff, int i, int j, int k) { m_SolutionSolver = new PlateConstantsSolver(m_PlateConfig); double ra0, de0; fit.GetRADEFromImageCoords(m_PlateConfig.CenterXImage, m_PlateConfig.CenterXImage, out ra0, out de0); m_SolutionSolver.InitPlateSolution(ra0, de0); List<IStar> consideredStars = new List<IStar>(); List<ulong> nonStellarStars = new List<ulong>(); foreach (IStar star in m_CelestialAllStars) { if (star.Mag < m_MinMag || star.Mag > m_MaxMag) continue; if (m_DetermineAutoLimitMagnitude && !double.IsNaN(m_DetectedLimitingMagnitude) && star.Mag > m_DetectedLimitingMagnitude) { #if ASTROMETRY_DEBUG Trace.Assert(false); #endif continue; } double x, y; fit.GetImageCoordsFromRADE(star.RADeg, star.DEDeg, out x, out y); if (x < 0 || x > m_PlateConfig.ImageWidth || y < 0 || y > m_PlateConfig.ImageHeight) continue; ImagePixel pixel = null; PSFFit psfFit; PSFFit asymPsfFit = null; //if (m_FitSettings.CenterDetectionMethod == StarCenterDetection.PSFFit) { if (m_Settings.PyramidRemoveNonStellarObject) m_StarMap.GetPSFFit((int)x, (int)y, PSFFittingMethod.NonLinearAsymetricFit, out asymPsfFit); pixel = m_StarMap.GetPSFFit((int)x, (int)y, PSFFittingMethod.NonLinearFit, out psfFit); } //else if (m_FitSettings.CenterDetectionMethod == StarCenterDetection.Centroid) { // NOTE: Centroid detection is way faster and PSF will not lead to big improvement considering the threshold for star matching //pixel = m_StarMap.GetCentroid((int)x, (int)y, (int)Math.Ceiling(m_Settings.SearchArea)); } if (pixel != null && psfFit.Certainty >= CorePyramidConfig.Default.MinDetectionLimitForSolutionImprovement / coeff) { consideredStars.Add(star); double distance = fit.GetDistanceInArcSec(pixel.XDouble, pixel.YDouble, x, y); if (distance < CorePyramidConfig.Default.MaxPreliminaryResidualForSolutionImprovement / coeff) { #if ASTROMETRY_DEBUG Trace.Assert(!double.IsNaN(pixel.XDouble)); Trace.Assert(!double.IsNaN(pixel.YDouble)); #endif if ( Math.Sqrt((x - pixel.XDouble) * (x - pixel.XDouble) + (y - pixel.YDouble) * (y - pixel.YDouble)) > CoreAstrometrySettings.Default.SearchArea) continue; pixel.SignalNoise = psfFit.Certainty; pixel.Brightness = psfFit.Brightness; m_SolutionSolver.AddStar(pixel, star); if (m_Settings.PyramidRemoveNonStellarObject && ( asymPsfFit.FWHM < m_Settings.MinReferenceStarFWHM || asymPsfFit.FWHM > m_Settings.MaxReferenceStarFWHM || asymPsfFit.ElongationPercentage > m_Settings.MaximumPSFElongation) ) { nonStellarStars.Add(star.StarNo); } } } } double ffl = fit.FitInfo.FittedFocalLength; m_ImprovedSolution = m_SolutionSolver.SolveWithLinearRegression(m_Settings, out m_FirstImprovedSolution); //if (m_ImprovedSolution != null && m_ImprovedSolution.FitInfo.AllStarPairs.Count < 12) //{ // // Attempt to reject errorous solutions with small number of fitted stars // int totalMatched = 0; // var largeFeatures = m_StarMap.Features.Where(x => x.MaxBrightnessPixels > 1).ToList(); // if (largeFeatures.Count > 5) // { // foreach (var feature in largeFeatures) // { // var ftrCenter = feature.GetCenter(); // // TODO: PFS Fit on the feature? // var matchedFittedStar = m_ImprovedSolution.FitInfo.AllStarPairs.FirstOrDefault( // x => // Math.Sqrt(Math.Pow(x.x - ftrCenter.XDouble, 2) + Math.Pow(x.x - ftrCenter.XDouble, 2)) < // 2); // if (matchedFittedStar != null) totalMatched++; // } // double percentLargeFeaturesMatched = 1.0*totalMatched/largeFeatures.Count; // if (percentLargeFeaturesMatched < 0.75) // { // if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceInfo()) // Trace.WriteLine(string.Format("Only {0:0.0}% ({1} features) of the large {2} features have been matched, where 75% is required.", percentLargeFeaturesMatched*100, totalMatched, largeFeatures.Count)); // // At least 75% of the bright features from the video need to be matched to stars for the solution to be accepted // m_ImprovedSolution = null; // } // } //} if (m_ImprovedSolution != null) { m_ImprovedSolution.FitInfo.FittedFocalLength = ffl; if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceWarning()) Trace.WriteLine(string.Format("Improved solution: {0} considered stars, UsedInSolution: {1}, ExcludedForHighResidual: {2}", m_ImprovedSolution.FitInfo.AllStarPairs.Count(), m_ImprovedSolution.FitInfo.AllStarPairs.Count(x => x.FitInfo.UsedInSolution), m_ImprovedSolution.FitInfo.AllStarPairs.Count(x => x.FitInfo.ExcludedForHighResidual))); // Fit was successful, exclude all unused non stellar objects so they // don't interfere with the included/excluded stars improved solution tests m_ImprovedSolution.FitInfo.AllStarPairs.RemoveAll(p => (p.FitInfo.ExcludedForHighResidual || !p.FitInfo.UsedInSolution) && nonStellarStars.Contains(p.StarNo)); // NOTE: How excluding stars for FWHM/Elongation may lead to incorrectly accepted solutions that include small number of stars // because the majority haven't been used for the fit. This is why we have another solution check here. if (m_ImprovedSolution.FitInfo.AllStarPairs.Count > 3) { List<PlateConstStarPair> usedStarPairs = m_ImprovedSolution.FitInfo.AllStarPairs.Where(p => p.FitInfo.UsedInSolution).ToList(); double maxIncludedMag = usedStarPairs.Max(p => p.Mag); int nonIncludedConsideredStars = consideredStars.Count(s => s.Mag <= maxIncludedMag) - usedStarPairs.Count; if (nonIncludedConsideredStars > CorePyramidConfig.Default.MaxFWHMExcludedImprovemntStarsCoeff * usedStarPairs.Count) { LogUnsuccessfulFitImage(m_ImprovedSolution, i, j, k, string.Format("More than {0:0.0}% of the stars ({1} stars) down to mag {2:0.00} have not been matched. Attempted stars: {3}, Coeff: {4:0.00}", CorePyramidConfig.Default.MaxFWHMExcludedImprovemntStarsCoeff * 100, nonIncludedConsideredStars, maxIncludedMag, m_SolutionSolver.Pairs.Count, nonIncludedConsideredStars / m_SolutionSolver.Pairs.Count)); m_ImprovedSolution = null; return; } List<double> intensities = usedStarPairs.Select(s => (double)s.Intensity).ToList(); List<double> mags = usedStarPairs.Select(s => s.Mag).ToList(); if (usedStarPairs.Count > 3) { LinearRegression reg = new LinearRegression(); int pointsAdded = 0; for (int ii = 0; ii < intensities.Count; ii++) { if (intensities[ii] > 0) { reg.AddDataPoint(intensities[ii], Math.Log10(mags[ii])); pointsAdded++; } } if (pointsAdded > 3) { reg.Solve(); if (Math.Pow(10, reg.StdDev) > CorePyramidConfig.Default.MagFitTestMaxStdDev || reg.A > CorePyramidConfig.Default.MagFitTestMaxInclination) { LogUnsuccessfulFitImage(m_ImprovedSolution, i, j, k, string.Format("Failing solution for failed magnitude fit. Intensity(Log10(Magntude)) = {1} * x + {2}, StdDev = {0:0.0000}, ChiSquare = {3:0.000}", Math.Pow(10, reg.StdDev), reg.A, reg.B, reg.ChiSquare)); m_ImprovedSolution = null; return; } } } } } }
internal void RegisterLinearFit(LeastSquareFittedAstrometry leastSquareFittedAstrometry) { LinearFit = leastSquareFittedAstrometry; }
private void LogUnsuccessfulFitImage(LeastSquareFittedAstrometry fit, int i, int j, int k, string traceMessage) { if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose()) Trace.WriteLine(traceMessage); if (DebugSaveAlignImages) SaveAlignImage(fit.FitInfo.AllStarPairs, i, j, k, false, traceMessage); }
public LeastSquareFittedAstrometry SolvePlateConstantsPhase4(double pyramidLimitMag) { double ra0deg, de0Deg; m_SolvedPlate.GetRADEFromImageCoords(m_SolvedPlate.Image.CenterXImage, m_SolvedPlate.Image.CenterYImage, out ra0deg, out de0Deg); FocalLengthFit distFit = m_ConstantsSolver.ComputeFocalLengthFit(); m_Context.PlateConfig.EffectiveFocalLength = m_Context.FieldSolveContext.FocalLength; distFit.GetFocalParameters(m_Context.PlateConfig.EffectiveFocalLength, out m_Context.PlateConfig.EffectivePixelWidth, out m_Context.PlateConfig.EffectivePixelHeight); DistanceBasedAstrometrySolver distMatch = new DistanceBasedAstrometrySolver( m_AstrometryController, m_Context.PlateConfig, m_AstrometrySettings, m_Context.FieldSolveContext.CatalogueStars, m_Context.FieldSolveContext.RADeg, m_Context.FieldSolveContext.DEDeg, m_Context.FieldSolveContext.DetermineAutoLimitMagnitude); distMatch.SetMinMaxMagOfStarsForAstrometry(CorePyramidConfig.Default.DefaultMinAstrometryMagnitude, 18); distMatch.SetMinMaxMagOfStarsForPyramidAlignment(CorePyramidConfig.Default.DefaultMinPyramidMagnitude, pyramidLimitMag); Trace.WriteLine(string.Format("Stars for alignment in range: {0:0.0} - {1:0.0} mag", CorePyramidConfig.Default.DefaultMinPyramidMagnitude, pyramidLimitMag)); Dictionary <PSFFit, IStar> manualStars = null; var threeStarFit = m_Context.PreliminaryFit as ThreeStarAstrometry; if (threeStarFit != null) { manualStars = new Dictionary <PSFFit, IStar>(); foreach (var kvp in threeStarFit.UserStars) { PSFFit psfFit; m_Context.StarMap.GetPSFFit(kvp.Key.X, kvp.Key.Y, PSFFittingMethod.NonLinearFit, out psfFit); if (psfFit != null && psfFit.IsSolved) { manualStars.Add(psfFit, kvp.Value); } } } distMatch.InitNewMatch(m_Context.StarMap, PyramidMatchType.PlateSolve, manualStars); #if ASTROMETRY_DEBUG Dictionary <int, ulong> debugInfo = new Dictionary <int, ulong>(); var starList = m_Context.SecondAstrometricFit.FitInfo.AllStarPairs .Where(p => !p.FitInfo.ExcludedForHighResidual); foreach (var x in starList) { if (!debugInfo.ContainsKey(x.FeatureId)) { debugInfo.Add(x.FeatureId, x.StarNo); } } foreach (var f in m_Context.StarMap.Features) { Trace.WriteLine(string.Format("{0} - {1}", f.FeatureId, debugInfo.ContainsKey(f.FeatureId) ? "INCLUDED" : "MISSING")); } distMatch.SetDebugData(new DistanceBasedAstrometrySolver.PyramidDebugContext() { ResolvedStars = debugInfo, ResolvedFocalLength = m_Context.SecondAstrometricFit.FitInfo.FittedFocalLength }); #endif LeastSquareFittedAstrometry fit = null; LeastSquareFittedAstrometry improvedFit = null; PlateConstantsSolver solver; distMatch.PerformMatch(out fit, out improvedFit, out solver); m_Context.DistanceBasedFit = fit; m_Context.ImprovedDistanceBasedFit = improvedFit; if (fit != null) { m_Context.PlateConstants = new TangraConfig.PersistedPlateConstants { EffectiveFocalLength = m_Context.PlateConfig.EffectiveFocalLength, EffectivePixelWidth = m_Context.PlateConfig.EffectivePixelWidth, EffectivePixelHeight = m_Context.PlateConfig.EffectivePixelHeight }; m_Context.ConstantsSolver = solver; if (improvedFit != null) { foreach (var pair in improvedFit.FitInfo.AllStarPairs) { if (pair.FitInfo.ExcludedForHighResidual) { continue; } Trace.WriteLine(string.Format("{6}; {0}; {1}; {2}; {3}; ({4}\", {5}\")", pair.RADeg, pair.DEDeg, pair.x.ToString("0.00"), pair.y.ToString("0.00"), pair.FitInfo.ResidualRAArcSec.ToString("0.00"), pair.FitInfo.ResidualDEArcSec.ToString("0.00"), pair.StarNo)); double x, y; improvedFit.GetImageCoordsFromRADE(pair.RADeg, pair.DEDeg, out x, out y); double dist = improvedFit.GetDistanceInArcSec(x, y, pair.x, pair.y); } } } else { m_Context.PlateConstants = null; } return(fit); }
public AstrometricSolutionImpl(LeastSquareFittedAstrometry astrometry, StarMagnitudeFit photometry, AstrometricState state, FieldSolveContext fieldSolveContext, MeasurementContext measurementContext) { StarCatalog = fieldSolveContext.StarCatalogueFacade.CatalogNETCode; UtcTime = fieldSolveContext.UtcTime; FrameNoOfUtcTime = fieldSolveContext.FrameNoOfUtcTime; AutoLimitMagnitude = (float)fieldSolveContext.AutoLimitMagnitude; ResolvedFocalLength = (float)fieldSolveContext.FocalLength; if (astrometry != null) { ResolvedCenterRADeg = (float)astrometry.RA0Deg; ResolvedCenterDEDeg = (float)astrometry.DE0Deg; StdDevRAArcSec = (float)astrometry.StdDevRAArcSec; StdDevDEArcSec = (float)astrometry.StdDevDEArcSec; ArcSecsInPixel = 1 / astrometry.GetDistanceInPixels(1); } else { ResolvedCenterRADeg = float.NaN; ResolvedCenterDEDeg = float.NaN; StdDevRAArcSec = float.NaN; StdDevDEArcSec = float.NaN; ArcSecsInPixel = 0; } if (state.SelectedObject != null) { m_UserObject = new TangraUserObjectImpl(); m_UserObject.RADeg = (float)state.SelectedObject.RADeg; m_UserObject.DEDeg = (float)state.SelectedObject.DEDeg; m_UserObject.X = (float)state.SelectedObject.X0; m_UserObject.Y = (float)state.SelectedObject.Y0; if (state.IdentifiedObjects != null && state.IdentifiedObjects.Count == 1) { foreach (IIdentifiedObject idObj in state.IdentifiedObjects) { if (AngleUtility.Elongation(idObj.RAHours * 15.0, idObj.DEDeg, state.SelectedObject.RADeg, state.SelectedObject.DEDeg) * 3600 < 120) { m_UserObject.ResolvedName = idObj.ObjectName; break; } } } } InstrumentalDelay = measurementContext.InstrumentalDelay; InstrumentalDelayUnits = measurementContext.InstrumentalDelayUnits.ToString(); FrameTimeType = measurementContext.FrameTimeType.ToString(); IntegratedFramesCount = measurementContext.IntegratedFramesCount; IntegratedExposureSeconds = measurementContext.IntegratedExposureSeconds; AavIntegration = measurementContext.AavIntegration; AavStackedMode = measurementContext.AavStackedMode; VideoFileFormat = measurementContext.VideoFileFormat.ToString(); NativeVideoFormat = measurementContext.NativeVideoFormat; if (!string.IsNullOrEmpty(state.IdentifiedObjectToMeasure)) { ObjectDesignation = MPCObsLine.GetObjectCode(state.IdentifiedObjectToMeasure); } else if (state.IdentifiedObjects != null && state.IdentifiedObjects.Count == 1) { ObjectDesignation = MPCObsLine.GetObjectCode(state.IdentifiedObjects[0].ObjectName); } ObservatoryCode = fieldSolveContext.ObsCode; CatalogueCode = measurementContext.StarCatalogueFacade.CatalogNETCode; m_MeasurementsImpl = new List <TangraAstrometricMeasurementImpl>(); if (state.Measurements != null) { foreach (var mea in state.Measurements) { m_MeasurementsImpl.Add(new TangraAstrometricMeasurementImpl() { DEDeg = mea.DEDeg, RADeg = mea.RADeg, FrameNo = mea.FrameNo, SolutionUncertaintyRACosDEArcSec = mea.SolutionUncertaintyRACosDEArcSec, SolutionUncertaintyDEArcSec = mea.SolutionUncertaintyDEArcSec, FWHMArcSec = mea.FWHMArcSec, Detection = mea.Detection, SNR = mea.SNR, UncorrectedTimeStamp = mea.FrameTimeStamp, Mag = mea.Mag }); } } m_MatchedStarImpl = new List <TangraMatchedStarImpl>(); if (astrometry != null) { foreach (PlateConstStarPair pair in astrometry.FitInfo.AllStarPairs) { if (pair.FitInfo.UsedInSolution) { var star = new TangraMatchedStarImpl() { X = (float)pair.x, Y = (float)pair.y, RADeg = (float)pair.RADeg, DEDeg = (float)pair.DEDeg, StarNo = pair.StarNo, ExcludedForHighResidual = pair.FitInfo.ExcludedForHighResidual, ResidualRAArcSec = (float)pair.FitInfo.ResidualRAArcSec, ResidualDEArcSec = (float)pair.FitInfo.ResidualDEArcSec, DetectionCertainty = (float)pair.DetectionCertainty, PSFAmplitude = (int)pair.Intensity, IsSaturated = pair.IsSaturated, Mag = (float)pair.Mag }; TangraCatalogStarImpl catStar = null; IStar catalogStar = fieldSolveContext.CatalogueStars.Find(s => s.StarNo == pair.StarNo); if (catalogStar != null) { if (catalogStar is UCAC4Entry) { catStar = new TangraAPASSStar(); } else { catStar = new TangraCatalogStarImpl(); } catStar.StarNo = catalogStar.StarNo; catStar.MagR = (float)catalogStar.MagR; catStar.MagV = (float)catalogStar.MagV; catStar.MagB = (float)catalogStar.MagB; catStar.Mag = (float)catalogStar.Mag; if (catalogStar is UCAC3Entry) { UCAC3Entry ucac3Star = (UCAC3Entry)catalogStar; catStar.MagJ = (float)(ucac3Star.jmag * 0.001); catStar.MagK = (float)(ucac3Star.kmag * 0.001); catStar.RAJ2000Deg = (float)ucac3Star.RACat; catStar.DEJ2000Deg = (float)ucac3Star.DECat; } else if (catalogStar is UCAC2Entry) { UCAC2Entry ucac2Star = (UCAC2Entry)catalogStar; catStar.MagJ = (float)(ucac2Star._2m_J * 0.001); catStar.MagK = (float)(ucac2Star._2m_Ks * 0.001); catStar.RAJ2000Deg = (float)ucac2Star.RACat; catStar.DEJ2000Deg = (float)ucac2Star.DECat; } else if (catalogStar is NOMADEntry) { NOMADEntry nomadStar = (NOMADEntry)catalogStar; catStar.MagJ = (float)(nomadStar.m_J * 0.001); catStar.MagK = (float)(nomadStar.m_K * 0.001); catStar.RAJ2000Deg = (float)nomadStar.RACat; catStar.DEJ2000Deg = (float)nomadStar.DECat; } else if (catalogStar is UCAC4Entry) { UCAC4Entry ucac4Star = (UCAC4Entry)catalogStar; catStar.MagJ = (float)(ucac4Star.MagJ); catStar.MagK = (float)(ucac4Star.MagK); catStar.RAJ2000Deg = (float)ucac4Star.RACat; catStar.DEJ2000Deg = (float)ucac4Star.DECat; ((TangraAPASSStar)catStar).B = (float)ucac4Star.MagB; ((TangraAPASSStar)catStar).V = (float)ucac4Star.MagV; ((TangraAPASSStar)catStar).g = (float)ucac4Star.Mag_g; ((TangraAPASSStar)catStar).r = (float)ucac4Star.Mag_r; ((TangraAPASSStar)catStar).i = (float)ucac4Star.Mag_i; ((TangraAPASSStar)catStar).e_B = ucac4Star.apase_B * 0.001f; ((TangraAPASSStar)catStar).e_V = ucac4Star.apase_V * 0.001f; ((TangraAPASSStar)catStar).e_g = ucac4Star.apase_g * 0.001f; ((TangraAPASSStar)catStar).e_r = ucac4Star.apase_r * 0.001f; ((TangraAPASSStar)catStar).e_i = ucac4Star.apase_i * 0.001f; } } star.CatalogStar = catStar; if (photometry != null) { IStar photometryStar = photometry.StarNumbers.FirstOrDefault(s => s.StarNo == pair.StarNo); if (photometryStar != null) { int idx = photometry.StarNumbers.IndexOf(photometryStar); star.Intensity = (float)photometry.Intencities[idx]; star.IsSaturated = photometry.SaturatedFlags[idx]; star.MeaSignalMethod = ConvertSignalMethod(photometry.MeaSignalMethod); star.MeaBackgroundMethod = ConvertBackgroundMethod(photometry.MeaBackgroundMethod); star.MeaSingleApertureSize = photometry.MeaSingleAperture; star.MeaBackgroundPixelCount = photometry.MeaBackgroundPixelCount; star.MeaSaturationLevel = photometry.MeaSaturationLevel; } } m_MatchedStarImpl.Add(star); } } } }
// TODO: Use the imeplementation in the MainForm instead private void DrawHighResFeature(ImagePixel pixel, PlateConstStarPair selectedPair, LeastSquareFittedAstrometry astrometry) { int x0 = pixel.X; int y0 = pixel.Y; if (x0 < 15) { x0 = 15; } if (y0 < 15) { y0 = 15; } if (x0 > AstrometryContext.Current.FullFrame.Width - 15) { x0 = AstrometryContext.Current.FullFrame.Width - 15; } if (y0 > AstrometryContext.Current.FullFrame.Height - 15) { y0 = AstrometryContext.Current.FullFrame.Height - 15; } int bytes; int bytesPerPixel; int selIdx; Bitmap featureBitmap = new Bitmap(31 * 8, 31 * 8, PixelFormat.Format24bppRgb); m_VideoController.UpdateZoomedImage(featureBitmap, pixel); BitmapData zoomedData = featureBitmap.LockBits(new Rectangle(0, 0, 31 * 8, 31 * 8), ImageLockMode.ReadWrite, featureBitmap.PixelFormat); try { bytes = zoomedData.Stride * featureBitmap.Height; byte[] zoomedValues = new byte[bytes]; Marshal.Copy(zoomedData.Scan0, zoomedValues, 0, bytes); bytesPerPixel = AstrometryContext.Current.BytesPerPixel; byte saturatedR = TangraConfig.Settings.Color.Saturation.R; byte saturatedG = TangraConfig.Settings.Color.Saturation.G; byte saturatedB = TangraConfig.Settings.Color.Saturation.B; selIdx = 0; for (int y = 0; y < 31; y++) { for (int x = 0; x < 31; x++) { for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { int zoomedX = 8 * x + i; int zoomedY = 8 * y + j; int zoomedIdx = zoomedData.Stride * zoomedY + zoomedX * bytesPerPixel; if (zoomedValues[zoomedIdx] > TangraConfig.Settings.Photometry.Saturation.Saturation8Bit) { // Saturation detected zoomedValues[zoomedIdx] = saturatedR; zoomedValues[zoomedIdx + 1] = saturatedG; zoomedValues[zoomedIdx + 2] = saturatedB; } } } selIdx++; } } Marshal.Copy(zoomedValues, 0, zoomedData.Scan0, bytes); } finally { featureBitmap.UnlockBits(zoomedData); } Pen starPen = catalogStarPen; double xFitUnscaled = pixel.XDouble; double yFitUnscaled = pixel.YDouble; if (selectedPair != null && selectedPair.FitInfo.UsedInSolution) { starPen = referenceStarPen; astrometry.GetImageCoordsFromRADE(selectedPair.RADeg, selectedPair.DEDeg, out xFitUnscaled, out yFitUnscaled); } else if (selectedPair != null && selectedPair.FitInfo.ExcludedForHighResidual) { starPen = rejectedStarPen; astrometry.GetImageCoordsFromRADE(selectedPair.RADeg, selectedPair.DEDeg, out xFitUnscaled, out yFitUnscaled); } else { starPen = unrecognizedStarPen; } double xFit = (8 * (xFitUnscaled - x0 + 16)) - 4; double yFit = (8 * (yFitUnscaled - y0 + 16)) - 4; }
internal void RegisterLinearFit(LeastSquareFittedAstrometry leastSquareFittedAstrometry) { LinearFit = leastSquareFittedAstrometry; }
public static CalibrationContext Deserialize(byte[] data) { CalibrationContext ctx = new CalibrationContext(); BinaryFormatter fmt = new BinaryFormatter(); using (MemoryStream memStr = new MemoryStream(data)) using (StreamReader rdr = new StreamReader(memStr)) { int version = (int)fmt.Deserialize(memStr); if (version > 0) { object obj = fmt.Deserialize(memStr); try { ctx.PlateConfig = (AstroPlate)obj; } catch (Exception) { ctx.PlateConfig = AstroPlate.FromReflectedObject(obj); } obj = fmt.Deserialize(memStr); try { ctx.StarMap = (StarMap)obj; } catch (Exception) { ctx.StarMap = Tangra.Model.Astro.StarMap.FromReflectedObject(obj); } int top = (int)fmt.Deserialize(memStr); int left = (int)fmt.Deserialize(memStr); int width = (int)fmt.Deserialize(memStr); int height = (int)fmt.Deserialize(memStr); ctx.FitExcludeArea = new Rectangle(top, left, width, height); obj = fmt.Deserialize(memStr); try { ctx.FieldSolveContext = (FieldSolveContext)obj; } catch (Exception) { ctx.FieldSolveContext = FieldSolveContext.FromReflectedObject(obj); } if (version > 1) { bool noNull = (bool)fmt.Deserialize(memStr); if (noNull) { obj = fmt.Deserialize(memStr); try { ctx.PreliminaryFit = (DirectTransRotAstrometry)obj; } catch (Exception) { ctx.PreliminaryFit = DirectTransRotAstrometry.FromReflectedObject(obj); } } noNull = (bool)fmt.Deserialize(memStr); if (noNull) { obj = fmt.Deserialize(memStr); try { ctx.FirstAstrometricFit = (LeastSquareFittedAstrometry)obj; } catch (Exception) { ctx.FirstAstrometricFit = LeastSquareFittedAstrometry.FromReflectedObject(obj); } } noNull = (bool)fmt.Deserialize(memStr); if (noNull) { obj = fmt.Deserialize(memStr); try { ctx.SecondAstrometricFit = (LeastSquareFittedAstrometry)obj; } catch (Exception) { ctx.SecondAstrometricFit = LeastSquareFittedAstrometry.FromReflectedObject(obj); } } noNull = (bool)fmt.Deserialize(memStr); if (noNull) { obj = fmt.Deserialize(memStr); try { ctx.DistanceBasedFit = (LeastSquareFittedAstrometry)obj; } catch (Exception) { ctx.DistanceBasedFit = LeastSquareFittedAstrometry.FromReflectedObject(obj); } } noNull = (bool)fmt.Deserialize(memStr); if (noNull) { obj = fmt.Deserialize(memStr); try { ctx.ImprovedDistanceBasedFit = (LeastSquareFittedAstrometry)obj; } catch (Exception) { ctx.ImprovedDistanceBasedFit = LeastSquareFittedAstrometry.FromReflectedObject(obj); } } if (version > 2) { FocalLengthFit flf = null; noNull = (bool)fmt.Deserialize(memStr); if (noNull) { obj = fmt.Deserialize(memStr); try { flf = (FocalLengthFit)obj; } catch (Exception) { flf = FocalLengthFit.FromReflectedObject(obj); } } ctx.ConstantsSolver = new PlateConstantsSolver(ctx.PlateConfig); ctx.ConstantsSolver.SetFocalLengthFit(flf); } } else { ctx.PreliminaryFit = (DirectTransRotAstrometry)fmt.Deserialize(memStr); } } } return(ctx); }
public void DrawCatalogStarsFit(Graphics g) { if (m_CatalogueStars == null) { m_LimitMag = -100; return; } bool hasManualStars = m_Is3StarIdMode && m_UserStarIdentification != null && m_UserStarIdentification.Count > 0; LeastSquareFittedAstrometry astrometry = null; astrometry = FittedAstrometryFromUserSelectedFitGrade(); IAstrometricFit fit = null; if (astrometry != null) { fit = astrometry; } else { fit = m_SolvedPlate; } if (fit != null) { double limitMag = (astrometry != null && astrometry.FitInfo.AllStarPairs.Count > 0) ? astrometry.FitInfo.AllStarPairs.Max(p => p.Mag) : m_LimitMag; foreach (IStar star in m_CatalogueStars) { if (star.Mag > limitMag) { continue; } double x, y; fit.GetImageCoordsFromRADE(star.RADeg, star.DEDeg, out x, out y); Pen starPen = catalogStarPen; Brush labelBruish = catalogBrushUnrecognized; if (astrometry != null) { PlateConstStarPair pair = astrometry.FitInfo.AllStarPairs.Find((p) => p.StarNo == star.StarNo); if (pair != null && pair.FitInfo.UsedInSolution) { starPen = referenceStarPen; labelBruish = catalogBrushReference; } else if (pair != null && pair.FitInfo.ExcludedForHighResidual) { starPen = rejectedStarPen; labelBruish = catalogBrushRejected; } else { starPen = unrecognizedStarPen; labelBruish = catalogBrushUnrecognized; } if (pair != null) { g.DrawLine(starPen, (float)x, (float)y, (float)pair.x, (float)pair.y); } } if (!m_Is3StarIdMode || astrometry != null) { float rad = (float)GetStarDiameter(m_LimitMag, 5, star.Mag) / 2; g.DrawEllipse(starPen, (float)x - rad, (float)y - rad, 2 * rad, 2 * rad); } if (m_ShowLabels || m_ShowMagnitudes) { string label; if (m_ShowLabels && m_ShowMagnitudes) { label = string.Format("{0} ({1}m)", star.GetStarDesignation(0), star.Mag); } else if (m_ShowLabels) { label = string.Format("{0}", star.GetStarDesignation(0)); } else { label = string.Format("{0}m", star.Mag); } g.DrawString(label, m_StarInfoFont, labelBruish, (float)x + 10, (float)y + 10); } } if (m_Is3StarIdMode && astrometry == null) { // Draw all features from the starMap (unless the configuration has been solved) if (AstrometryContext.Current.StarMap != null) { foreach (StarMapFeature feature in AstrometryContext.Current.StarMap.Features) { ImagePixel center = feature.GetCenter(); PSFFit psfFit; AstrometryContext.Current.StarMap.GetPSFFit(center.X, center.Y, PSFFittingMethod.NonLinearAsymetricFit, out psfFit); #if ASTROMETRY_DEBUG PSFFit psfFit2; AstrometryContext.Current.StarMap.GetPSFFit(center.X, center.Y, PSFFittingMethod.NonLinearFit, out psfFit2); double elong = psfFit.RX0 / psfFit.RY0; double elongPerc = Math.Abs(1 - elong) * 100; Trace.WriteLine(string.Format("({0:0}, {1:0}) Rx = {2:0.00} Ry = {3:0.00}, e = {4:0.000} ({5:0}%), FWHMxy = {6:0.0} | FWHMxx = {7:0.0}", center.X, center.Y, psfFit.RX0, psfFit.RY0, elong, elongPerc, psfFit.FWHM, psfFit2.FWHM)); #endif Pen pen = catalogStarPen; #if ASTROMETRY_DEBUG if (psfFit.FWHM < TangraConfig.Settings.Astrometry.MinReferenceStarFWHM || psfFit.FWHM > TangraConfig.Settings.Astrometry.MaxReferenceStarFWHM || psfFit.ElongationPercentage > TangraConfig.Settings.Astrometry.MaximumPSFElongation) { pen = rejectedStarPen; } #endif g.DrawLine(pen, (float)center.XDouble - 9, (float)center.YDouble, (float)center.XDouble - 5, (float)center.YDouble); g.DrawLine(pen, (float)center.XDouble + 5, (float)center.YDouble, (float)center.XDouble + 9, (float)center.YDouble); g.DrawLine(pen, (float)center.XDouble, (float)center.YDouble - 9, (float)center.XDouble, (float)center.YDouble - 5); g.DrawLine(pen, (float)center.XDouble, (float)center.YDouble + 5, (float)center.XDouble, (float)center.YDouble + 9); } } } else { if (m_Grid) { DrawEquatorialGrid(g); } } #region Draw the manual single star identification if (hasManualStars) { foreach (PSFFit psf in m_UserStarIdentification.Keys) { IStar star = m_UserStarIdentification[psf]; float rad = (float)GetStarDiameter(m_LimitMag, 5, star.Mag) / 2; g.DrawEllipse(Pens.DarkRed, (float)psf.XCenter - rad, (float)psf.YCenter - rad, 2 * rad, 2 * rad); g.DrawEllipse(Pens.DarkRed, (float)psf.XCenter - rad - 2, (float)psf.YCenter - rad - 2, 2 * rad + 4, 2 * rad + 4); } } #endregion ; } UpdateToolControlDisplay(); }
public PerformMatchResult PerformMatch( out LeastSquareFittedAstrometry distanceBasedSolution, out LeastSquareFittedAstrometry improvedSolution, out PlateConstantsSolver solver) { DistanceBasedContext.FieldAlignmentResult alignmentResult = null; improvedSolution = null; #if UNIT_TESTS Flags.Reset(); #endif m_PerformanceWatch.Reset(); m_PerformanceWatch.Start(); try { if (m_StarMap.FeaturesCount < TangraConfig.Settings.Astrometry.MinimumNumberOfStars) { distanceBasedSolution = null; solver = null; return(PerformMatchResult.FieldAlignmentFailed); } if (!m_IsCalibration && m_Solution != null) { // Try using the cache from the last time alignmentResult = Context.DoFieldAlignment(m_StarMap, m_Solution.FitInfo, false); m_Solution = GetSolution(alignmentResult); #if UNIT_TESTS Flags.CacheFromLastTimeAttempted = true; Flags.CacheFromLastTimeSuccessful = m_Solution != null; #endif } if (m_Solution == null && !m_IsCalibration && m_ManualStarMatch != null) { // Try using the manual star match alignmentResult = Context.DoFieldAlignment(m_StarMap, m_ManualStarMatch); m_Solution = GetSolution(alignmentResult); #if UNIT_TESTS Flags.ManualMatchAttempted = true; Flags.ManualMatchSuccessful = m_Solution != null; #endif } if (m_Solution == null && !m_RatioBasedFittedFocalLengthIsDerived && !m_FitSettings.PyramidForceFixedFocalLength && !m_IsCalibration) { m_OperationNotifier.NotifyBeginLongOperation("Performing a plate solve ..."); try { // If this is the first fit, then fit a focal length alignmentResult = Context.DoFieldAlignmentFitFocalLength(m_StarMap); m_Solution = GetSolution(alignmentResult); if (m_Solution != null) { m_RatioBasedFittedFocalLengthIsDerived = true; m_RatioBasedFittedFocalLength = m_Solution.FitInfo.FittedFocalLength; } else { if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceInfo()) { Trace.WriteLine(string.Format("No solution after reaching combination {0} with {1} features.", Context.CurrentCombination, m_StarMap.FeaturesCount)); } } } finally { m_OperationNotifier.NotifyEndLongOperation(); } #if UNIT_TESTS Flags.RatioBasedFocalLengthFitAttempted = true; Flags.RatioBasedFocalLengthFitSuccessful = m_RatioBasedFittedFocalLengthIsDerived; #endif } else { if (m_Solution == null) { if (m_RatioBasedFittedFocalLengthIsDerived && !m_IsCalibration) { alignmentResult = Context.DoFieldAlignment(m_StarMap, m_RatioBasedFittedFocalLength); m_Solution = GetSolution(alignmentResult); #if UNIT_TESTS Flags.FitWithPreFittedFocalLengthAttempted = true; Flags.FitWithPreFittedFocalLengthSuccessful = m_Solution != null; #endif } else { alignmentResult = Context.DoFieldAlignment(m_StarMap); m_Solution = GetSolution(alignmentResult); #if UNIT_TESTS Flags.FitWithFixedFocalLengthAttempted = true; Flags.FitWithFixedFocalLengthSuccessful = m_Solution != null; #endif } } } m_SearchAborted = Context.m_AbortSearch; if (alignmentResult != null) { distanceBasedSolution = (LeastSquareFittedAstrometry)alignmentResult.Solution; improvedSolution = (LeastSquareFittedAstrometry)alignmentResult.ImprovedSolution; m_Solution = GetSolution(alignmentResult); solver = alignmentResult.Solver; } else { distanceBasedSolution = m_Solution; solver = null; } if (m_SearchAborted) { return(PerformMatchResult.SearchAborted); } #if ASTROMETRY_DEBUG if (m_Solution != null) { // No need to keep the debug log any longer when the fit is successful AstrometricFitDebugger.Reset(); } #endif if (m_Solution != null) { // Clear manually identified starting position in a case of a successful plate solve m_ManualStarMatch = null; } return(m_Solution != null ? PerformMatchResult.FitSucceessfull : PerformMatchResult.FitImprovementFailed); } finally { // Reset the manually matched stars after every fit attempt m_ManualStarMatch = null; m_PerformanceWatch.Stop(); if (m_Solution != null) { if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceError()) { Trace.WriteLine(string.Format( "Pyramid Match Successful: {0} ms, {1} stars total, aligned on {2} stars, {3} stars matched {4}. Combination: {5}", m_PerformanceWatch.ElapsedMilliseconds, m_CelestialStars.Count, alignmentResult != null ? (alignmentResult.Solution as LeastSquareFittedAstrometry).FitInfo.NumberOfStarsUsedInSolution() : 0, improvedSolution != null ? improvedSolution.FitInfo.NumberOfStarsUsedInSolution().ToString() : "N/A", improvedSolution != null ? string.Format(" ({0}-{1} mag)", Context.ImprovedSolutionIncludedMinMag.ToString("0.00"), Context.ImprovedSolutionIncludedMaxMag.ToString("0.00")) : null, alignmentResult != null ? alignmentResult.MatchedTriangle : null)); } } else { if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceError()) { Trace.WriteLine(string.Format("Pyramid Match Failed: {0} ms, {1} stars total, NO MATCH", m_PerformanceWatch.ElapsedMilliseconds, m_CelestialStars.Count)); } if (Context.DebugResolvedStars != null) { foreach (DistanceBasedContext.DebugTripple tripple in Context.m_DebugTripples) { if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose()) { Trace.WriteLine(string.Format("DEBUG ALIGN: Missed alignment on {0}-{1}-{2}", tripple.Id1, tripple.Id2, tripple.Id3)); } } } } #if ASTROMETRY_DEBUG Trace.Assert(!m_DetermineAutoLimitMagnitude || m_Solution == null || m_Solution.FitInfo.DetectedLimitingMagnitude != 0); #endif } }
public void NextFrame(int frameNo, IAstroImage astroImage, IStarMap starMap, LeastSquareFittedAstrometry astrometricFit) { IsTrackedSuccessfully = false; int searchRadius = (int)Math.Ceiling(Math.Max(m_LastMovementPixels, CoreAstrometrySettings.Default.PreMeasureSearchCentroidRadius)); PSFFit psfFit = null; int startingX = (int)TrackedObject.LastKnownX; int startingY = (int)TrackedObject.LastKnownY; if (m_RepeatedIntergationPositions * 4 < m_PastFrameNos.Count) { var expectedPos = GetExpectedPosition(frameNo); if (expectedPos != null) { startingX = expectedPos.X; startingY = expectedPos.Y; } } var nearbyFeatures = starMap.GetFeaturesInRadius(startingX, startingY, searchRadius).ToArray(); var nonStarNearbyFeature = new List <StarMapFeature>(); foreach (var feature in nearbyFeatures) { var center = feature.GetCenter(); var referenceStarFeatures = astrometricFit.FitInfo.AllStarPairs.Where(x => x.FitInfo.UsedInSolution).ToList(); var refStar = referenceStarFeatures.FirstOrDefault(s => Math.Sqrt((s.x - center.X) * (s.x - center.X) + (s.y - center.Y) * (s.y - center.Y)) < 2); double raf, def; astrometricFit.GetRADEFromImageCoords(center.XDouble, center.YDouble, out raf, out def); var pastKnownStar = m_LastFrameStars.FirstOrDefault(s => AngleUtility.Elongation(s.RADeg, s.DEDeg, raf, def) * 3600.0 < 2); if (refStar == null && pastKnownStar == null) { nonStarNearbyFeature.Add(feature); } } if (nonStarNearbyFeature.Count > 0) { StarMapFeature closestFeature = nonStarNearbyFeature[0]; var lastKnownCenter = new ImagePixel(TrackedObject.LastKnownX, TrackedObject.LastKnownY); var smallestDistance = lastKnownCenter.DistanceTo(closestFeature.GetCenter()); for (int i = 1; i < nonStarNearbyFeature.Count; i++) { var distance = lastKnownCenter.DistanceTo(nonStarNearbyFeature[i].GetCenter()); if (distance < smallestDistance) { smallestDistance = distance; closestFeature = nonStarNearbyFeature[i]; } } if (closestFeature != null) { var center = closestFeature.GetCenter(); AstrometryContext.Current.StarMap.GetPSFFit(center.X, center.Y, PSFFittingMethod.NonLinearFit, out psfFit); } } if (psfFit == null) { // The expected location cannot be matched with any brighter feature so it is likely a faint object // with no brighter objects around. Lets find the brightest (faint) object in the are and use it ImagePixel centroid = AstrometryContext.Current.StarMap.GetCentroid(startingX, startingY, searchRadius); if (centroid != null) { AstrometryContext.Current.StarMap.GetPSFFit(centroid.X, centroid.Y, PSFFittingMethod.NonLinearFit, out psfFit); } } if (psfFit != null) { double ra, de; astrometricFit.GetRADEFromImageCoords(psfFit.XCenter, psfFit.YCenter, out ra, out de); double maxPosDiffArcSec = astrometricFit.GetDistanceInArcSec(astrometricFit.Image.CenterXImage, astrometricFit.Image.CenterYImage, astrometricFit.Image.CenterXImage + Math.Max(m_LastMovementPixels, CoreAstrometrySettings.Default.MaxAllowedDefaultMotionInPixels), astrometricFit.Image.CenterYImage); if (!double.IsNaN(TrackedObject.RAHours)) { double posDif = 3600 * AngleUtility.Elongation(15 * TrackedObject.RAHours, TrackedObject.DEDeg, ra, de); if (posDif > maxPosDiffArcSec) { // NOTE: Not a valid measurement Trace.WriteLine(string.Format("The target position is too far from the last measured position", posDif)); return; } } TrackedObject.RAHours = ra / 15.0; TrackedObject.DEDeg = de; if (TrackedObject.PSFFit != null) { m_LastMovementPixels = 1.2 * ImagePixel.ComputeDistance(TrackedObject.LastKnownX, psfFit.XCenter, TrackedObject.LastKnownY, psfFit.YCenter); } TrackedObject.LastKnownX = psfFit.XCenter; TrackedObject.LastKnownY = psfFit.YCenter; TrackedObject.PSFFit = psfFit; var lastKnownCenter = new ImagePixel(TrackedObject.LastKnownX, TrackedObject.LastKnownY); var thisFrameStars = astrometricFit.FitInfo.AllStarPairs.Where(x => lastKnownCenter.DistanceTo(x.x, x.y) > 2 * psfFit.FWHM).ToList(); if (thisFrameStars.Count > 0) { m_LastFrameStars = thisFrameStars.Select(x => new Star(x.StarNo, x.RADeg, x.DEDeg, x.Mag) as IStar).ToList(); } IsTrackedSuccessfully = true; } if (psfFit != null && psfFit.XCenter > 0 && psfFit.YCenter > 0) { m_PastFramePosX.Add(psfFit.XCenter); m_PastFramePosY.Add(psfFit.YCenter); m_PastFrameNos.Add(frameNo); } }