Пример #1
0
        public PerformMatchResult PerformMatch(out LeastSquareFittedAstrometry improvedSolution)
        {
            LeastSquareFittedAstrometry distanceBasedSolution;
            PlateConstantsSolver        solver;

            return(PerformMatch(out distanceBasedSolution, out improvedSolution, out solver));
        }
Пример #2
0
        internal SolutionImprovementEntry(LeastSquareFittedAstrometry fit, int i, int j, int k)
        {
            FitToImprove = fit;

            this.i = i;
            this.j = j;
            this.k = k;
        }
Пример #3
0
        internal SolutionImprovementEntry(LeastSquareFittedAstrometry fit, int i, int j, int k)
        {
            FitToImprove = fit;

            this.i = i;
            this.j = j;
            this.k = k;
        }
Пример #4
0
        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();
                    }
                }
            }
        }
Пример #5
0
        /// <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);
        }
Пример #6
0
        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;
        }
Пример #7
0
        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;
        }
Пример #8
0
        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;
                }
            }
        }
Пример #9
0
        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
            }
        }
Пример #12
0
        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;
                            }                            
                        }
                    }
				}
			}
		}
Пример #13
0
 internal void RegisterLinearFit(LeastSquareFittedAstrometry leastSquareFittedAstrometry)
 {
     LinearFit = leastSquareFittedAstrometry;
 }
Пример #14
0
        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);

        }
Пример #15
0
        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);
        }
Пример #16
0
        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);
                    }
                }
            }
        }
Пример #17
0
        // 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;
        }
Пример #18
0
 internal void RegisterLinearFit(LeastSquareFittedAstrometry leastSquareFittedAstrometry)
 {
     LinearFit = leastSquareFittedAstrometry;
 }
Пример #19
0
        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);
        }
Пример #20
0
        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();
        }
Пример #21
0
        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
            }
        }
Пример #22
0
        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);
            }
        }