예제 #1
0
        public double GetDistanceInArcSec(double distanceInPixels)
        {
            double dxRad = (distanceInPixels) * EffectivePixelWidth / (EffectiveFocalLength * 1000.0);
            double dyRad = (distanceInPixels) * EffectivePixelHeight / (EffectiveFocalLength * 1000.0);

            return(AngleUtility.Elongation(0, 0, dxRad * 180 / Math.PI, dyRad * 180 / Math.PI) * 3600.0);
        }
예제 #2
0
        public double GetDistanceInArcSec(double x1, double y1, double x2, double y2, double effectiveFocalLength)
        {
            double dxRad = (x1 - x2) * EffectivePixelWidth / (effectiveFocalLength * 1000.0);
            double dyRad = (y1 - y2) * EffectivePixelHeight / (effectiveFocalLength * 1000.0);

            return(AngleUtility.Elongation(0, 0, dxRad * 180 / Math.PI, dyRad * 180 / Math.PI) * 3600.0);
        }
예제 #3
0
        public double GetDistanceInArcSec(double x1, double y1, double x2, double y2)
        {
            double ra1, de1, ra2, de2;

            GetRADEFromImageCoords(x1, y1, out ra1, out de1);
            GetRADEFromImageCoords(x2, y2, out ra2, out de2);

            return(AngleUtility.Elongation(ra1, de1, ra2, de2) * 3600.0);
        }
예제 #4
0
        public double GetMaxFOVInArcSec()
        {
            if (double.IsNaN(EffectiveFocalLength))
            {
                throw new InvalidOperationException("EffectiveFocalLength must be set before computing MaxFOVInDeg");
            }

            double dxRad = m_ImageWidth * EffectivePixelWidth / (EffectiveFocalLength * 1000.0);
            double dyRad = m_ImageHeight * EffectivePixelHeight / (EffectiveFocalLength * 1000.0);

            return(AngleUtility.Elongation(0, 0, dxRad * 180 / Math.PI, dyRad * 180 / Math.PI) * 3600.0);
        }
예제 #5
0
        internal IIdentifiedObject GetIdentifiedObjectAt(double raDeg, double deDeg)
        {
            foreach (IIdentifiedObject entry in m_IdentifiedObjects)
            {
                double distance = AngleUtility.Elongation(raDeg, deDeg, entry.RAHours * 15, entry.DEDeg);
                if (distance < CoreAstrometrySettings.Default.IdentifiedObjectResidualInArcSec)
                {
                    return(entry);
                }
            }

            return(null);
        }
예제 #6
0
        private void GenerateSimulatedVideo(object state)
        {
            InvokeUpdateUI(2, 0, true);

            try
            {
                ModelConfig modelConfig = (ModelConfig)state;

                modelConfig.MaxPixelValue = modelConfig.IsAAVFile ? (uint)modelConfig.Integration * 255 : 255;

                double dxRad  = modelConfig.FrameWidth * modelConfig.PlatePixWidth / (modelConfig.PlateFocLength * 1000.0);
                double dyRad  = modelConfig.FrameHeight * modelConfig.PlatePixHeight / (modelConfig.PlateFocLength * 1000.0);
                double fovDeg = AngleUtility.Elongation(0, 0, dxRad * 180 / Math.PI, dyRad * 180 / Math.PI);

                var          catFac = new StarCatalogueFacade(TangraConfig.Settings.StarCatalogue);
                List <IStar> stars  = catFac.GetStarsInRegion(m_RA * 15, m_DE, 2 * fovDeg, modelConfig.LimitStarMag, 2000);

                if (modelConfig.IsAAVFile)
                {
                    GenerateAAVVideo(modelConfig, stars);
                }
                else
                {
                    GenerateAVIVideo(modelConfig, stars);
                }

                if (modelConfig.DarkFrameMean > 0 && cbxPhotometricFilter != null)
                {
                    // Save the dark frame
                    float[,] averagedFrame = new float[modelConfig.FrameWidth, modelConfig.FrameHeight];
                    for (int x = 0; x < modelConfig.FrameWidth; x++)
                    {
                        for (int y = 0; y < modelConfig.FrameHeight; y++)
                        {
                            averagedFrame[x, y] = m_SimulatedDarkFrame[x, y];
                        }
                    }

                    InvokeSaveDarkFrame(modelConfig, averagedFrame);
                }
            }
            finally
            {
                InvokeUpdateUI(2, 100, false);
            }
        }
예제 #7
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;
                }
            }
        }
예제 #8
0
        internal AbsFluxSpectra(AbsFluxInputFile inputFile)
        {
            InputFile  = inputFile;
            IsComplete = false;

            if (!string.IsNullOrEmpty(inputFile.Target))
            {
                // First try to read the target from the export
                m_DisplayName       = inputFile.Target;
                m_ExtractedStarName = null;
            }
            else
            {
                // Then try to parse the star from the file
                Match match = STAR_DESIGNATION_REGEX.Match(inputFile.FileName);
                if (match.Success && !string.IsNullOrEmpty(match.Value))
                {
                    m_ExtractedStarName = match.Value.Replace('_', ' ').Replace("  ", " ").Trim();
                    m_DisplayName       = m_ExtractedStarName;
                }
            }

            HasObjectCoordinates = !float.IsNaN(inputFile.Latitude) && !float.IsNaN(inputFile.Longitude) &&
                                   !float.IsNaN(inputFile.RAHours) && !float.IsNaN(inputFile.DEDeg);

            HasObservationTime = inputFile.Epoch != DateTime.MinValue;

            if (HasObservationTime && HasObjectCoordinates)
            {
                // If we have the center of the field saved in the export then identify the standard star by the position
                List <CalSpecStar> standardsInOneDegreeRadius = CalSpecDatabase.Instance.Stars.Where(x => AngleUtility.Elongation(x.RA_J2000_Hours * 15, x.DE_J2000_Deg, InputFile.RAHours * 15, InputFile.DEDeg) < 1).ToList();
                if (standardsInOneDegreeRadius.Count == 1)
                {
                    m_CalSpecStar = standardsInOneDegreeRadius[0];
                    m_DisplayName = m_CalSpecStar.AbsFluxStarId;

                    IsComplete  = true;
                    PlotSpectra = true;
                }
            }

            if (inputFile.Epoch > DateTime.MinValue)
            {
                m_DisplayName += string.Format(" ({0} UT)", inputFile.Epoch.ToString("HH:mm"));
            }

            if (string.IsNullOrEmpty(m_DisplayName))
            {
                m_DisplayName = Path.GetFileNameWithoutExtension(inputFile.FileName);
            }


            DataFromWavelength = (int)Math.Ceiling(inputFile.Wavelengths[0]);
            DataFromWavelength = (int)Math.Floor(inputFile.Wavelengths[inputFile.Wavelengths.Count - 1]);
        }
예제 #9
0
        public ProcessingReturnValues FitAndPlotSlowFlyby(
            Dictionary <int, SingleMultiFrameMeasurement> measurements,
            FlybyMeasurementContext meaContext,
            FittingContext fittingContext,
            FittingValue fittingValue,
            GetFrameStateDataCallback getFrameStateDataCallback,
            Graphics g, FlybyPlottingContext plottingContext, float xScale, float yScale, int imageWidth, int imageHight,
            out double motionRate)
        {
            try
            {
                #region Building Test Cases
                if (m_DumpTestCaseData)
                {
                    var mvSer = new XmlSerializer(typeof(FlybyMeasurementContext));
                    var sb    = new StringBuilder();
                    using (var wrt = new StringWriter(sb))
                    {
                        mvSer.Serialize(wrt, meaContext);
                    }
                    Trace.WriteLine(sb.ToString());
                    var fcSer = new XmlSerializer(typeof(FittingContext));
                    sb.Clear();
                    using (var wrt = new StringWriter(sb))
                    {
                        fcSer.Serialize(wrt, fittingContext);
                    }
                    Trace.WriteLine(sb.ToString());

                    var smfmSer = new XmlSerializer(typeof(SingleMultiFrameMeasurement));
                    foreach (int key in measurements.Keys)
                    {
                        sb.Clear();
                        using (var wrt2 = new StringWriter(sb))
                        {
                            smfmSer.Serialize(wrt2, measurements[key]);
                            if (measurements[key].FrameNo != key)
                            {
                                throw new InvalidOperationException();
                            }
                            Trace.WriteLine(sb.ToString());
                        }
                    }
                }
                #endregion

                // Do linear regression, use residual based exclusion rules
                // Report the interpolated position at the middle of the measured interva
                // Don't forget to add the video normal position flag in the OBS file
                // Expect elongated images and apply instrumental delay corrections

                motionRate = double.NaN;

                var rv = new ProcessingReturnValues();

                int numFramesUser = 0;

                rv.EarliestFrame = int.MaxValue;
                rv.LatestFrame   = int.MinValue;

                var intervalValues  = new Dictionary <int, Tuple <List <double>, List <double> > >();
                var intervalMedians = new Dictionary <double, double>();
                var intervalWeights = new Dictionary <double, double>();

                LinearRegression regression = null;
                if (measurements.Values.Count > 1)
                {
                    rv.EarliestFrame = measurements.Values.Select(m => m.FrameNo).Min();
                    rv.LatestFrame   = measurements.Values.Select(m => m.FrameNo).Max();

                    var minUncertainty = meaContext.MinPositionUncertaintyPixels * meaContext.ArsSecsInPixel;

                    foreach (SingleMultiFrameMeasurement measurement in measurements.Values)
                    {
                        int integrationInterval = (measurement.FrameNo - fittingContext.FirstFrameIdInIntegrationPeroid) / fittingContext.IntegratedFramesCount;

                        Tuple <List <double>, List <double> > intPoints;
                        if (!intervalValues.TryGetValue(integrationInterval, out intPoints))
                        {
                            intPoints = Tuple.Create(new List <double>(), new List <double>());
                            intervalValues.Add(integrationInterval, intPoints);
                        }

                        if (fittingValue == FittingValue.RA)
                        {
                            intPoints.Item1.Add(measurement.RADeg);
                            intPoints.Item2.Add(ComputePositionWeight(measurement.SolutionUncertaintyRACosDEArcSec, measurement, minUncertainty, fittingContext.Weighting));
                        }
                        else
                        {
                            intPoints.Item1.Add(measurement.DEDeg);
                            intPoints.Item2.Add(ComputePositionWeight(measurement.SolutionUncertaintyDEArcSec, measurement, minUncertainty, fittingContext.Weighting));
                        }
                    }

                    if (intervalValues.Count > 2)
                    {
                        regression = new LinearRegression();

                        foreach (int integratedFrameNo in intervalValues.Keys)
                        {
                            Tuple <List <double>, List <double> > data = intervalValues[integratedFrameNo];

                            double median;
                            double medianWeight;

                            WeightedMedian(data, out median, out medianWeight);

                            // Assign the data point to the middle of the integration interval (using frame numbers)
                            //
                            // |--|--|--|--|--|--|--|--|
                            // |           |           |
                            //
                            // Because the time associated with the first frame is the middle of the frame, but the
                            // time associated with the middle of the interval is the end of the field then the correction
                            // is (N / 2) - 0.5 frames when integration is used or no correction when integration of x1 is used.

                            double dataPointFrameNo =
                                rv.EarliestFrame +
                                fittingContext.IntegratedFramesCount * integratedFrameNo
                                + (fittingContext.IntegratedFramesCount / 2)
                                - (fittingContext.IntegratedFramesCount > 1 ? 0.5 : 0);

                            intervalMedians.Add(dataPointFrameNo, median);
                            intervalWeights.Add(dataPointFrameNo, medianWeight);
                            if (fittingContext.Weighting != WeightingMode.None)
                            {
                                regression.AddDataPoint(dataPointFrameNo, median, medianWeight);
                            }
                            else
                            {
                                regression.AddDataPoint(dataPointFrameNo, median);
                            }
                        }

                        regression.Solve();

                        var    firstPos       = measurements[rv.EarliestFrame];
                        var    lastPos        = measurements[rv.LatestFrame];
                        double distanceArcSec = AngleUtility.Elongation(firstPos.RADeg, firstPos.DEDeg, lastPos.RADeg, lastPos.DEDeg) * 3600;
                        var    firstTime      = GetTimeForFrame(fittingContext, rv.EarliestFrame, meaContext.FirstVideoFrame, getFrameStateDataCallback, firstPos.FrameTimeStamp);
                        var    lastTime       = GetTimeForFrame(fittingContext, rv.LatestFrame, meaContext.FirstVideoFrame, getFrameStateDataCallback, lastPos.FrameTimeStamp);
                        double elapsedSec     = new TimeSpan(lastTime.UT.Ticks - firstTime.UT.Ticks).TotalSeconds;
                        motionRate = distanceArcSec / elapsedSec;
                    }
                }

                FrameTime resolvedTime = null;
                if (int.MinValue != meaContext.UserMidFrame)
                {
                    // Find the closest video 'normal' MPC time and compute the frame number for it
                    // Now compute the RA/DE for the computed 'normal' frame
                    resolvedTime = GetTimeForFrame(fittingContext, meaContext.UserMidFrame, meaContext.FirstVideoFrame, getFrameStateDataCallback, measurements[meaContext.UserMidFrame].FrameTimeStamp);

                    #region Plotting Code
                    if (g != null)
                    {
                        float xPosBeg = (float)(resolvedTime.ClosestNormalIntervalFirstFrameNo - rv.EarliestFrame) * xScale + 5;
                        float xPosEnd = (float)(resolvedTime.ClosestNormalIntervalLastFrameNo - rv.EarliestFrame) * xScale + 5;

                        g.FillRectangle(s_NormalTimeIntervalHighlightBrush, xPosBeg, 1, (xPosEnd - xPosBeg), imageHight - 2);
                    }
                    #endregion
                }

                Dictionary <double, double> secondPassData = new Dictionary <double, double>();

                int minFrameId = measurements.Keys.Min();

                #region Plotting Code
                if (g != null)
                {
                    foreach (SingleMultiFrameMeasurement measurement in measurements.Values)
                    {
                        float x = (measurement.FrameNo - minFrameId) * xScale + 5;

                        ProcessingValues val = new ProcessingValues()
                        {
                            Value  = fittingValue == FittingValue.RA ? measurement.RADeg : measurement.DEDeg,
                            StdDev = fittingValue == FittingValue.RA ? measurement.StdDevRAArcSec / 3600.0 : measurement.StdDevDEArcSec / 3600.0
                        };

                        double valueFrom = val.Value - val.StdDev;
                        double valueTo   = val.Value + val.StdDev;

                        float yFrom = (float)(valueFrom - plottingContext.MinValue) * yScale + 5;
                        float yTo   = (float)(valueTo - plottingContext.MinValue) * yScale + 5;

                        g.DrawLine(plottingContext.IncludedPen, x, yFrom, x, yTo);
                        g.DrawLine(plottingContext.IncludedPen, x - 1, yFrom, x + 1, yFrom);
                        g.DrawLine(plottingContext.IncludedPen, x - 1, yTo, x + 1, yTo);
                    }
                }
                #endregion

                foreach (double integrFrameNo in intervalMedians.Keys)
                {
                    double val = intervalMedians[integrFrameNo];

                    double fittedValAtFrame = regression != null
                        ? regression.ComputeY(integrFrameNo)
                        : double.NaN;

                    bool included = Math.Abs(fittedValAtFrame - val) < 3 * regression.StdDev;

                    #region Plotting Code
                    if (g != null)
                    {
                        if (fittingContext.IntegratedFramesCount > 1)
                        {
                            Pen mPen = included ? plottingContext.IncludedPen : plottingContext.ExcludedPen;

                            float x = (float)(integrFrameNo - minFrameId) * xScale + 5;
                            float y = (float)(val - plottingContext.MinValue) * yScale + 5;

                            g.DrawEllipse(mPen, x - 3, y - 3, 6, 6);
                            g.DrawLine(mPen, x - 5, y - 5, x + 5, y + 5);
                            g.DrawLine(mPen, x + 5, y - 5, x - 5, y + 5);
                        }
                    }
                    #endregion

                    if (included)
                    {
                        secondPassData.Add(integrFrameNo, val);
                    }
                }

                #region Second Pass
                regression = null;
                if (secondPassData.Count > 2)
                {
                    regression = new LinearRegression();
                    foreach (double frameNo in secondPassData.Keys)
                    {
                        if (fittingContext.Weighting != WeightingMode.None)
                        {
                            regression.AddDataPoint(frameNo, secondPassData[frameNo], intervalWeights[frameNo]);
                        }
                        else
                        {
                            regression.AddDataPoint(frameNo, secondPassData[frameNo]);
                        }
                    }
                    regression.Solve();
                }
                #endregion

                if (regression != null)
                {
                    #region Plotting Code
                    if (g != null)
                    {
                        double leftFittedVal  = regression.ComputeY(rv.EarliestFrame);
                        double rightFittedVal = regression.ComputeY(rv.LatestFrame);

                        double err = 3 * regression.StdDev;

                        float leftAve  = (float)(leftFittedVal - plottingContext.MinValue) * yScale + 5;
                        float rightAve = (float)(rightFittedVal - plottingContext.MinValue) * yScale + 5;
                        float leftX    = 5 + (float)(rv.EarliestFrame - rv.EarliestFrame) * xScale;
                        float rightX   = 5 + (float)(rv.LatestFrame - rv.EarliestFrame) * xScale;

                        g.DrawLine(plottingContext.AveragePen, leftX, leftAve - 1, rightX, rightAve - 1);
                        g.DrawLine(plottingContext.AveragePen, leftX, leftAve, rightX, rightAve);
                        g.DrawLine(plottingContext.AveragePen, leftX, leftAve + 1, rightX, rightAve + 1);

                        float leftMin  = (float)(leftFittedVal - err - plottingContext.MinValue) * yScale + 5;
                        float leftMax  = (float)(leftFittedVal + err - plottingContext.MinValue) * yScale + 5;
                        float rightMin = (float)(rightFittedVal - err - plottingContext.MinValue) * yScale + 5;
                        float rightMax = (float)(rightFittedVal + err - plottingContext.MinValue) * yScale + 5;

                        g.DrawLine(plottingContext.AveragePen, leftX, leftMin, rightX, rightMin);
                        g.DrawLine(plottingContext.AveragePen, leftX, leftMax, rightX, rightMax);
                    }
                    #endregion

                    if (int.MinValue != meaContext.UserMidFrame &&
                        resolvedTime != null)
                    {
                        // Find the closest video 'normal' MPC time and compute the frame number for it
                        // Now compute the RA/DE for the computed 'normal' frame

                        double fittedValueUncertainty;
                        double fittedValueAtMiddleFrame = regression.ComputeYWithError(resolvedTime.ClosestNormalFrameNo, out fittedValueUncertainty);

                        Trace.WriteLine(string.Format("{0}; Included: {1}; Normal Frame No: {2}; Fitted Val: {3} +/- {4:0.00}",
                                                      meaContext.UserMidValue.ToString("0.00000"),
                                                      numFramesUser, resolvedTime.ClosestNormalFrameNo,
                                                      AstroConvert.ToStringValue(fittedValueAtMiddleFrame, "+HH MM SS.T"),
                                                      regression.StdDev * 60 * 60));

                        // Report the interpolated position at the middle of the measured interval
                        // Don't forget to add the video normal position flag in the OBS file
                        // Expect elongated images and apply instrumental delay corrections

                        rv.FittedValue                  = fittedValueAtMiddleFrame;
                        rv.FittedValueTime              = resolvedTime.ClosestNormalFrameTime;
                        rv.IsVideoNormalPosition        = true;
                        rv.FittedNormalFrame            = resolvedTime.ClosestNormalFrameNo;
                        rv.FittedValueUncertaintyArcSec = fittedValueUncertainty * 60 * 60;

                        #region Plotting Code
                        if (g != null)
                        {
                            // Plot the frame
                            float xPos = (float)(resolvedTime.ClosestNormalFrameNo - rv.EarliestFrame) * xScale + 5;
                            float yPos = (float)(rv.FittedValue - plottingContext.MinValue) * yScale + 5;
                            g.DrawLine(Pens.Yellow, xPos, 1, xPos, imageHight - 2);
                            g.FillEllipse(Brushes.Yellow, xPos - 3, yPos - 3, 6, 6);
                        }
                        #endregion
                    }
                    else
                    {
                        rv.FittedValue = double.NaN;
                    }
                }
                else
                {
                    rv.FittedValue = double.NaN;
                }

                return(rv);
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.GetFullStackTrace());
                motionRate = 0;
                return(null);
            }
        }
예제 #10
0
        private bool LeastSquareSolve(double ra0Deg, double de0Deg, int minNumberOfStars)
        {
            int[] NUM_CONSTANTS = new int[] { 3, 6, 10 };

            SafeMatrix A = new SafeMatrix(m_StarPairs.Count, NUM_CONSTANTS[(int)m_FitOrder]);
            SafeMatrix X = new SafeMatrix(m_StarPairs.Count, 1);
            SafeMatrix Y = new SafeMatrix(m_StarPairs.Count, 1);

            SafeMatrix AReverse = new SafeMatrix(m_StarPairs.Count, NUM_CONSTANTS[(int)m_FitOrder]);
            SafeMatrix XReverse = new SafeMatrix(m_StarPairs.Count, 1);
            SafeMatrix YReverse = new SafeMatrix(m_StarPairs.Count, 1);

            int numStars = 0;

            for (int i = 0; i < m_StarPairs.Count; i++)
            {
                m_StarPairs[i].FitInfo.UsedInSolution = false;

                if (m_StarPairs[i].FitInfo.ExcludedForHighResidual)
                {
                    continue;
                }

                numStars++;
                m_StarPairs[i].FitInfo.UsedInSolution = true;

                ConfigureObservation(A, AReverse, i);

                X[i, 0]        = m_StarPairs[i].ExpectedXTang;
                Y[i, 0]        = m_StarPairs[i].ExpectedYTang;
                XReverse[i, 0] = m_StarPairs[i].x;
                YReverse[i, 0] = m_StarPairs[i].y;
            }

            // Insufficient stars to solve the plate
            if (numStars < minNumberOfStars)
            {
                if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose())
                {
                    Debug.WriteLine(string.Format("Insufficient number of stars to do a fit. At least {0} stars requested.", minNumberOfStars));
                }

                return(false);
            }

            SafeMatrix a_T    = A.Transpose();
            SafeMatrix aa     = a_T * A;
            SafeMatrix aa_inv = aa.Inverse();
            SafeMatrix bx     = (aa_inv * a_T) * X;
            SafeMatrix by     = (aa_inv * a_T) * Y;

            if (ReadSolvedConstants(bx, by))
            {
                a_T    = AReverse.Transpose();
                aa     = a_T * AReverse;
                aa_inv = aa.Inverse();
                bx     = (aa_inv * a_T) * XReverse;
                by     = (aa_inv * a_T) * YReverse;

                ReadSolvedReversedConstants(bx, by);
            }

            double residualSum         = 0;
            double residualSumArcSecRA = 0;
            double residualSumArcSecDE = 0;
            int    numResiduals        = 0;

            var absResRAArcSec = new List <double>();
            var absResDEArcSec = new List <double>();

            for (int i = 0; i < m_StarPairs.Count; i++)
            {
                double computedXTang, computedYTang;
                GetTangentCoordsFromImageCoords(m_StarPairs[i].x, m_StarPairs[i].y, out computedXTang, out computedYTang);

                m_StarPairs[i].FitInfo.ResidualXTang = m_StarPairs[i].ExpectedXTang - computedXTang;
                m_StarPairs[i].FitInfo.ResidualYTang = m_StarPairs[i].ExpectedYTang - computedYTang;

                double raComp, deComp;
                TangentPlane.TangentToCelestial(computedXTang, computedYTang, ra0Deg, de0Deg, out raComp, out deComp);

                m_StarPairs[i].FitInfo.ResidualRAArcSec = 3600.0 * AngleUtility.Elongation(m_StarPairs[i].RADeg, 0, raComp, 0);
                m_StarPairs[i].FitInfo.ResidualDEArcSec = 3600.0 * AngleUtility.Elongation(0, m_StarPairs[i].DEDeg, 0, deComp);

                if (!m_StarPairs[i].FitInfo.UsedInSolution)
                {
                    continue;
                }
                numResiduals++;
                residualSum         += Math.Abs(m_StarPairs[i].FitInfo.ResidualXTang * m_StarPairs[i].FitInfo.ResidualYTang);
                residualSumArcSecRA += m_StarPairs[i].FitInfo.ResidualRAArcSec * m_StarPairs[i].FitInfo.ResidualRAArcSec;
                residualSumArcSecDE += m_StarPairs[i].FitInfo.ResidualDEArcSec * m_StarPairs[i].FitInfo.ResidualDEArcSec;
                absResRAArcSec.Add(Math.Abs(m_StarPairs[i].FitInfo.ResidualRAArcSec));
                absResDEArcSec.Add(Math.Abs(m_StarPairs[i].FitInfo.ResidualDEArcSec));
            }

            Variance         = residualSum / (numResiduals - 1);
            VarianceArcSecRA = residualSumArcSecRA / (numResiduals - 1);
            VarianceArcSecDE = residualSumArcSecDE / (numResiduals - 1);

            // Uncertainty based on Astrometrica's formula of median residual devided by SQRT(num stars)
            UncertaintyArcSecRA = absResRAArcSec.Median() / Math.Sqrt(numResiduals);
            UncertaintyArcSecDE = absResDEArcSec.Median() / Math.Sqrt(numResiduals);


            return(true);
        }
예제 #11
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);
            }
        }
예제 #12
0
        protected virtual void DrawEquatorialGrid(Graphics g)
        {
            // We want at least 5 but no more than 10 RA and DE lines to fit the diagonal
            double diagonalInArcSec = m_SolvedPlate.GetDistanceInArcSec(0, 0, m_Image.ImageWidth, m_Image.ImageHeight);

            double ra0, de0;

            m_SolvedPlate.GetRADEFromImageCoords(m_Image.CenterXImage, m_Image.CenterYImage, out ra0, out de0);
            Debug.Assert(Math.Abs(m_SolvedPlate.RA0Deg - ra0) < 1 / 3600.0);
            Debug.Assert(Math.Abs(m_SolvedPlate.DE0Deg - de0) < 1 / 3600.0);

            // We are not drawing lines when too close to the poles
            if (de0 + 2 * diagonalInArcSec / 3600.0 > 90)
            {
                return;
            }
            if (de0 - 2 * diagonalInArcSec / 3600.0 < -90)
            {
                return;
            }

            int MAX_GRID_LINES = 10;
            int MIN_GRID_LINES = 5;

            int[] intervals = new int[] { 1, 5, 10, 30, 60, 60 * 5, 60 * 10, 60 * 30, 60 * 60 };

            double deFrom, deTo;

            #region Calculating  the interval in declination
            double maxArcSec = diagonalInArcSec / MIN_GRID_LINES;
            double minArcSec = diagonalInArcSec / MAX_GRID_LINES;

            int deInterval = -1;
            for (int i = 0; i < intervals.Length; i++)
            {
                if (intervals[i] >= minArcSec &&
                    intervals[i] <= maxArcSec)
                {
                    deInterval = intervals[i];
                    break;
                }
                else if (intervals[i] < minArcSec)
                {
                    deInterval = intervals[i];
                }
            }
            #endregion

            double raFrom, raTo;
            #region Calculating  the interval in right accension

            double[] raArr = new double[4];
            double[] deArr = new double[4];
            m_SolvedPlate.GetRADEFromImageCoords(0, 0, out raArr[0], out deArr[0]);
            m_SolvedPlate.GetRADEFromImageCoords(0, m_Image.ImageHeight, out raArr[1], out deArr[1]);
            m_SolvedPlate.GetRADEFromImageCoords(m_Image.ImageWidth, 0, out raArr[2], out deArr[2]);
            m_SolvedPlate.GetRADEFromImageCoords(m_Image.ImageWidth, m_Image.ImageHeight, out raArr[3], out deArr[3]);

            // From the RA of the 4 corners we need to find the fromRA and toRA
            double raMin = double.MaxValue, raMax = double.MinValue;
            int    minIdx = 0, maxIdx = 0;
            for (int i = 0; i < 4; i++)
            {
                if (raArr[i] > raMax)
                {
                    raMax  = raArr[i];
                    maxIdx = i;
                }

                if (raArr[i] < raMin)
                {
                    raMin  = raArr[i];
                    minIdx = i;
                }
            }
            double shortestDistance = AngleUtility.Elongation(raArr[minIdx], 0, raArr[maxIdx], 0);
            if (shortestDistance < (raArr[maxIdx] - raArr[minIdx]) - 10 / 3600.0 /* tolerance 10" */)
            {
                // We are going accross the 0 point
                Debug.Assert(false, "This is not implemented yet");
                return;
                //raFrom = 0;
                //raTo = 0;
                //for (int i = 0; i < 4; i++)
                //{
                //    if (i == minIdx) continue;
                //    if (i == maxIdx) continue;

                //    if (raArr[0] > raMax)
                //    {
                //        raMax = raArr[0];
                //        maxIdx = 1;
                //    }

                //    if (raArr[0] < raMin)
                //    {
                //        raMin = raArr[0];
                //        minIdx = i;
                //    }
                //}
                //raTo = raArr[maxIdx];
            }
            else
            {
                raFrom = raArr[minIdx];
                raTo   = raArr[maxIdx];
            }

            minArcSec = 3600.0 * (raTo - raFrom) / (15 * MAX_GRID_LINES);
            maxArcSec = 3600.0 * (raTo - raFrom) / (15 * MIN_GRID_LINES);
            int raInterval = -1;
            for (int i = 0; i < intervals.Length; i++)
            {
                if (intervals[i] >= minArcSec &&
                    intervals[i] <= maxArcSec)
                {
                    raInterval = intervals[i];
                    break;
                }
                else if (intervals[i] < minArcSec)
                {
                    raInterval = intervals[i];
                }
            }
            #endregion

#if DEBUG
            if (raInterval == -1 || deInterval == -1)
            {
                Debug.Assert(false, "Problem with raInterval or deInterval");
                return;
            }
#endif

            raFrom = (Math.Floor((raFrom * 3600.0) / (15 * raInterval)) - 1) * 15 * raInterval / 3600.0;
            raTo   = (Math.Ceiling((raTo * 3600.0) / (15 * raInterval)) + 1) * 15 * raInterval / 3600.0;

            deFrom = (Math.Floor((de0 * 3600.0 - (diagonalInArcSec / 2)) / (deInterval)) - 1) * deInterval / 3600.0;
            deTo   = (Math.Ceiling((de0 * 3600.0 + (diagonalInArcSec / 2)) / (deInterval)) + 1) * deInterval / 3600.0;

            //Debug.WriteLine(string.Format("Draw Grid -> C: ({0}, {1}) F:({2}, {3}) T:({4}, {5})",
            //    AstroConvert.ToStringValue(ra0, "HH MM SS.T"), AstroConvert.ToStringValue(de0, "+DD MM SS.T"),
            //    AstroConvert.ToStringValue(raFrom, "HH MM SS.T"), AstroConvert.ToStringValue(raTo, "HH MM SS.T"),
            //    AstroConvert.ToStringValue(deFrom, "+DD MM SS.T"), AstroConvert.ToStringValue(deTo, "+DD MM SS.T")));

            double x1, y1, x2, y2;
            double stepRA = (15 * raInterval) / 3600.0;
            double stepDE = deInterval / 3600.0;

            for (double ra = raFrom; ra <= raTo; ra += stepRA)
            {
                x1 = double.NaN; y1 = double.NaN;
                for (double de = deFrom; de < deTo; de += stepDE / 10.0)
                {
                    m_SolvedPlate.GetImageCoordsFromRADE(ra, de, out x2, out y2);
                    if (x2 >= 0 && x2 <= m_Image.ImageWidth && y2 >= 0 && y2 <= m_Image.ImageHeight)
                    {
                        if (!double.IsNaN(x1))
                        {
                            g.DrawLine(Pens.Purple, (float)x1, (float)y1, (float)x2, (float)y2);
                        }

                        x1 = x2; y1 = y2;
                    }
                }
            }

            for (double de = deFrom; de <= deTo; de += stepDE)
            {
                x1 = double.NaN; y1 = double.NaN;
                for (double ra = raFrom; ra < raTo; ra += stepRA / 10.0)
                {
                    m_SolvedPlate.GetImageCoordsFromRADE(ra, de, out x2, out y2);
                    if (x2 >= 0 && x2 <= m_Image.ImageWidth && y2 >= 0 && y2 <= m_Image.ImageHeight)
                    {
                        if (!double.IsNaN(x1))
                        {
                            g.DrawLine(Pens.Purple, (float)x1, (float)y1, (float)x2, (float)y2);
                        }

                        x1 = x2; y1 = y2;
                    }
                }
            }
        }
예제 #13
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);
                    }
                }
            }
        }
예제 #14
0
        public Bitmap ResolveObjects(
            TangraConfig.PhotometryReductionMethod photometryReductionMethod,
            TangraConfig.PsfQuadrature psfQuadrature,
            TangraConfig.PsfFittingMethod psfFittingMethod,
            TangraConfig.BackgroundMethod backgroundMethod,
            TangraConfig.PreProcessingFilter filter,
            Guid magnitudeBandId,
            Rectangle osdRectangleToExclude,
            Rectangle rectToInclude,
            bool limitByInclusion,
            IAstrometrySettings astrometrySettings,
            ObjectResolverSettings objectResolverSettings)
        {
            m_AstrometrySettings = astrometrySettings;

            StarMap starMap = new StarMap(
                astrometrySettings.PyramidRemoveNonStellarObject,
                astrometrySettings.MinReferenceStarFWHM,
                astrometrySettings.MaxReferenceStarFWHM,
                astrometrySettings.MaximumPSFElongation,
                astrometrySettings.LimitReferenceStarDetection);

            starMap.FindBestMap(StarMapInternalConfig.Default, m_Image, osdRectangleToExclude, rectToInclude, limitByInclusion);

            float r0 = 0;

            m_MagnitudeFit = StarMagnitudeFit.PerformFit(
                m_AstrometryController,
                m_VideoController,
                m_Image.Pixelmap.BitPixCamera,
                m_Image.Pixelmap.MaxSignalValue,
                m_Astrometry.FitInfo,
                photometryReductionMethod,
                psfQuadrature,
                psfFittingMethod,
                backgroundMethod,
                filter,
                m_Stars,
                magnitudeBandId,
                1.0f,
                TangraConfig.KnownCameraResponse.Undefined,
                null, null, null,
                ref r0);


            m_BackgroundFlux = m_MagnitudeFit.GetBackgroundIntencity();
            m_BackgroundMag  = m_MagnitudeFit.GetMagnitudeForIntencity(m_BackgroundFlux);

            if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose())
            {
                Trace.WriteLine(string.Format("Plate FWHM: {0}", 2 * Math.Sqrt(Math.Log(2)) * r0));
            }

            PeakPixelResolver resolver = new PeakPixelResolver(m_Image);

            resolver.ResolvePeakPixels(osdRectangleToExclude, rectToInclude, limitByInclusion, objectResolverSettings.ExcludeEdgeAreaPixels, objectResolverSettings.MinDistanceBetweenPeakPixels);

            List <double> identifiedMagnitudes = new List <double>();
            List <double> identifiedR0s        = new List <double>();

            m_IdentifiedObjects.Clear();
            m_UidentifiedObjects.Clear();

            foreach (KeyValuePair <int, int> peakPixel in resolver.PeakPixels.Keys)
            {
                int x = peakPixel.Key;
                int y = peakPixel.Value;

                bool   isSaturated;
                double intencity = m_MagnitudeFit.GetIntencity(new ImagePixel(255, x, y), out isSaturated);
                double magnitude = m_MagnitudeFit.GetMagnitudeForIntencity(intencity);

                if (magnitude < m_MaxMagForAstrometry)
                {
                    double RADeg, DEDeg;

                    PSFFit fit;
                    starMap.GetPSFFit(x, y, PSFFittingMethod.NonLinearFit, out fit);


                    if (fit.IMax < 0)
                    {
                        continue;
                    }
                    if (fit.IMax < fit.I0)
                    {
                        continue;
                    }
                    if (fit.Certainty < objectResolverSettings.MinCertainty)
                    {
                        continue;
                    }
                    if (fit.FWHM < objectResolverSettings.MinFWHM)
                    {
                        continue;
                    }
                    if (fit.IMax - fit.I0 < objectResolverSettings.MinAmplitude)
                    {
                        continue;
                    }

                    m_Astrometry.GetRADEFromImageCoords(fit.XCenter, fit.YCenter, out RADeg, out DEDeg);

                    // All stars closer than 2 arcsec to this position
                    List <IStar> matchingStars = m_Stars.Where(s => Math.Abs(AngleUtility.Elongation(s.RADeg, s.DEDeg, RADeg, DEDeg) * 3600.0) < objectResolverSettings.MaxStarMatchMagDif).ToList();

                    bool identified = false;
                    if (matchingStars.Count >= 1)
                    {
                        foreach (IStar star in matchingStars)
                        {
                            if (objectResolverSettings.MaxStarMatchMagDif >= Math.Abs(magnitude - star.Mag))
                            {
                                // The star is identified. Do we care more?
                                if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose())
                                {
                                    Trace.WriteLine(string.Format("STAR ({0}, {1}) No -> {2}; Mag -> {3} (Expected: {4}); R0 = {5}",
                                                                  x, y, star.StarNo, magnitude.ToString("0.00"), star.Mag.ToString("0.00"), fit.R0.ToString("0.0")));
                                }

                                identifiedMagnitudes.Add(magnitude);
                                identifiedR0s.Add(fit.R0);
                                m_IdentifiedObjects.Add(fit, star);
                                identified = true;
                                break;
                            }
                        }
                    }

                    if (matchingStars.Count == 0 ||
                        !identified)
                    {
                        // The object is not in the star database

                        // TODO: Test for hot pixel. Match to hot pixel profile from the brightest pixel in the area
                        m_UidentifiedObjects.Add(fit, magnitude);
                    }
                }
                else
                {
                    // Don't bother with too faint objects
                }
            }

            if (m_IdentifiedObjects.Count > 0)
            {
                double mean     = identifiedR0s.Average();
                double variance = 0;
                foreach (double rr0 in identifiedR0s)
                {
                    variance += (rr0 - mean) * (rr0 - mean);
                }
                variance = Math.Sqrt(variance / (m_IdentifiedObjects.Count - 1));
                double minR0 = mean - variance;
                double maxR0 = mean + variance;

                identifiedMagnitudes.Sort();
                double maxStarMag = identifiedMagnitudes[Math.Max(0, (int)Math.Truncate(0.9 * identifiedMagnitudes.Count))];

                if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose())
                {
                    Trace.WriteLine(string.Format("Max Star Mag: {0}; R0 ({1}, {2})", maxStarMag.ToString("0.00"), minR0.ToString("0.0"), maxR0.ToString("0.0")));
                }

                // NOTE: The R0 exclusion may ignore bright comets !
                m_UnknownObjects = m_UidentifiedObjects
                                   .Where(p => p.Value < maxStarMag && p.Key.R0 >= minR0 && p.Key.R0 <= maxR0)
                                   .ToDictionary(p => p.Key, p => p.Value);

                if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose())
                {
                    foreach (PSFFit obj in m_UnknownObjects.Keys)
                    {
                        Trace.WriteLine(string.Format("UNK: ({0}, {1}) Mag -> {2}; R0 = {3}", obj.XCenter.ToString("0.0"), obj.YCenter.ToString("0.0"), m_UnknownObjects[obj].ToString("0.00"), obj.R0.ToString("0.0")));
                    }
                }
            }

            Bitmap bitmap = m_Image.Pixelmap.CreateDisplayBitmapDoNotDispose();

            using (Graphics g = Graphics.FromImage(bitmap))
            {
                foreach (PSFFit star in m_IdentifiedObjects.Keys)
                {
                    float x = (float)star.XCenter;
                    float y = (float)star.YCenter;

                    g.DrawEllipse(Pens.GreenYellow, x - 5, y - 5, 10, 10);
                }

                foreach (PSFFit star in m_UnknownObjects.Keys)
                {
                    float x = (float)star.XCenter;
                    float y = (float)star.YCenter;

                    g.DrawEllipse(Pens.Tomato, x - 8, y - 8, 16, 16);
                }

                g.Save();
            }

            return(bitmap);
        }
예제 #15
0
        public FocalLengthFit ComputeFocalLengthFit()
        {
            if (m_FocalLengthFit != null)
            {
                return(m_FocalLengthFit);
            }

            List <DistSolveEntry> entries = new List <DistSolveEntry>();

            for (int i = 0; i < m_Pairs.Count; i++)
            {
                if (!m_Pairs[i].FitInfo.UsedInSolution)
                {
                    continue;
                }
                if (m_Pairs[i].FitInfo.ExcludedForHighResidual)
                {
                    continue;
                }

                for (int j = 0; j < m_Pairs.Count; j++)
                {
                    if (i == j)
                    {
                        continue;
                    }
                    if (!m_Pairs[j].FitInfo.UsedInSolution)
                    {
                        continue;
                    }
                    if (m_Pairs[j].FitInfo.ExcludedForHighResidual)
                    {
                        continue;
                    }

                    DistSolveEntry entry = new DistSolveEntry();
                    entry.DX = Math.Abs(m_Pairs[i].x - m_Pairs[j].x);
                    entry.DY = Math.Abs(m_Pairs[i].y - m_Pairs[j].y);

                    entry.StarNo1 = m_Pairs[i].StarNo;
                    entry.StarNo2 = m_Pairs[j].StarNo;

                    // NOTE: two ways of computing distances - by vx,vy,vz and Elongation()
                    //entry.DistRadians = Math.Acos(m_Pairs[i].VX * m_Pairs[j].VX + m_Pairs[i].VY * m_Pairs[j].VY + m_Pairs[i].VZ * m_Pairs[j].VZ);

                    double elong = AngleUtility.Elongation(m_Pairs[i].RADeg, m_Pairs[i].DEDeg, m_Pairs[j].RADeg, m_Pairs[j].DEDeg);
                    entry.DistRadians = elong * Math.PI / 180.0;

                    if (entry.DX == 0 || entry.DY == 0)
                    {
                        continue;
                    }

                    entries.Add(entry);
                }
            }

            SafeMatrix A = new SafeMatrix(entries.Count, 2);
            SafeMatrix X = new SafeMatrix(entries.Count, 1);

            int numStars = 0;

            foreach (DistSolveEntry entry in entries)
            {
                A[numStars, 0] = entry.DX * entry.DX;
                A[numStars, 1] = entry.DY * entry.DY;

                X[numStars, 0] = entry.DistRadians * entry.DistRadians;

                numStars++;
            }

            // Insufficient stars to solve the plate
            if (numStars < 3)
            {
                return(null);
            }

            SafeMatrix a_T    = A.Transpose();
            SafeMatrix aa     = a_T * A;
            SafeMatrix aa_inv = aa.Inverse();
            SafeMatrix bx     = (aa_inv * a_T) * X;

            double a = bx[0, 0];
            double b = bx[1, 0];

            double residualSum  = 0;
            int    numResiduals = 0;

            foreach (DistSolveEntry entry in entries)
            {
                entry.ResidualRadians = entry.DistRadians - Math.Sqrt(a * entry.DX * entry.DX + b * entry.DY * entry.DY);
                entry.ResidualPercent = entry.ResidualRadians * 100.0 / entry.DistRadians;
                entry.ResidualArcSec  = 3600.0 * entry.ResidualRadians * 180.0 / Math.PI;

                numResiduals++;
                residualSum += entry.ResidualRadians * entry.ResidualRadians;
            }

            double variance = Math.Sqrt(residualSum / (numResiduals - 1));

            return(new FocalLengthFit(a, b, variance, entries));
        }
예제 #16
0
        public ThreeStarAstrometry(AstroPlate image, Dictionary <ImagePixel, IStar> userStarIdentification, int tolerance)
        {
            if (userStarIdentification.Count != 3)
            {
                throw new InvalidOperationException();
            }

            Image     = image;
            UserStars = userStarIdentification.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

            double a0       = userStarIdentification.Values.Average(x => x.RADeg) * DEG_TO_RAD;
            double d0       = userStarIdentification.Values.Average(x => x.DEDeg) * DEG_TO_RAD;
            double corr     = double.MaxValue;
            int    attempts = 0;

            do
            {
                SafeMatrix AX = new SafeMatrix(3, 3);
                SafeMatrix X  = new SafeMatrix(3, 1);
                SafeMatrix AY = new SafeMatrix(3, 3);
                SafeMatrix Y  = new SafeMatrix(3, 1);

                int i = 0;
                foreach (var pixel in userStarIdentification.Keys)
                {
                    IStar  star = userStarIdentification[pixel];
                    double a    = star.RADeg * DEG_TO_RAD;
                    double d    = star.DEDeg * DEG_TO_RAD;

                    AX[i, 0] = pixel.XDouble;
                    AX[i, 1] = pixel.YDouble;
                    AX[i, 2] = 1;
                    AY[i, 0] = pixel.XDouble;
                    AY[i, 1] = pixel.YDouble;
                    AY[i, 2] = 1;

                    X[i, 0] = Math.Cos(d) * Math.Sin(a - a0) / (Math.Cos(d0) * Math.Cos(d) * Math.Cos(a - a0) + Math.Sin(d0) * Math.Sin(d));
                    Y[i, 0] = (Math.Cos(d0) * Math.Sin(d) - Math.Cos(d) * Math.Sin(d0) * Math.Cos(a - a0)) / (Math.Sin(d0) * Math.Sin(d) + Math.Cos(d0) * Math.Cos(d) * Math.Cos(a - a0));

                    i++;
                }

                SafeMatrix a_T    = AX.Transpose();
                SafeMatrix aa     = a_T * AX;
                SafeMatrix aa_inv = aa.Inverse();
                SafeMatrix bx     = (aa_inv * a_T) * X;

                m_A = bx[0, 0];
                m_B = bx[1, 0];
                m_C = bx[2, 0];

                a_T    = AY.Transpose();
                aa     = a_T * AY;
                aa_inv = aa.Inverse();
                bx     = (aa_inv * a_T) * Y;

                m_D = bx[0, 0];
                m_E = bx[1, 0];
                m_F = bx[2, 0];

                m_A0Rad = a0;
                m_D0Rad = d0;

                double ra_c, de_c;
                GetRADEFromImageCoords(Image.CenterXImage, Image.CenterYImage, out ra_c, out de_c);

                corr = AngleUtility.Elongation(ra_c, de_c, a0 * RAD_TO_DEG, d0 * RAD_TO_DEG) * 3600;
                a0   = ra_c * DEG_TO_RAD;
                d0   = de_c * DEG_TO_RAD;
                attempts++;
            }while (corr > tolerance && attempts < MAX_ATTEMPTS);

            Success = corr <= tolerance;
        }