예제 #1
0
        internal NotMeasuredReasons DoNonLinearProfileFittingPhotometry(
            PSFFit fit,
            uint[,] matrix, int x0Int, int y0Int, float x0, float y0,
            float aperture, int matrixSize, bool useNumericalQadrature,
            bool isFullyDisappearingOccultedStar,
            uint[,] backgroundArea,
            bool mayBeOcculted /* Some magic based on a pure guess */,
            double refinedFWHM, float bgAnnulusFactor)
        {
            double distance  = ImagePixel.ComputeDistance(fit.XCenter, x0, fit.YCenter, y0);
            double tolerance = isFullyDisappearingOccultedStar
                ? m_TimesHigherPositionToleranceForFullyOccultedStars * m_PositionTolerance
                : m_PositionTolerance;

            if (fit.IsSolved)
            {
                SetPsfFitReading(fit, aperture, useNumericalQadrature, backgroundArea, bgAnnulusFactor);
            }
            else
            {
                m_Aperture        = aperture;
                m_XCenter         = (float)fit.X0_Matrix;
                m_YCenter         = (float)fit.Y0_Matrix;
                m_TotalReading    = 0;
                m_TotalBackground = 0;
            }

            if (!fit.IsSolved ||                                               // The PSF solution failed, mark the reading invalid
                (distance > tolerance && !mayBeOcculted) ||                    // If this doesn't look like a full disappearance, then make the reading invalid
                (fit.FWHM < 0.5 * refinedFWHM || fit.FWHM > 1.5 * refinedFWHM) // The FWHM is too small or too large, make the reading invalid
                )
            {
                return(!fit.IsSolved
                        ? NotMeasuredReasons.MeasurementPSFFittingFailed
                        : (distance > tolerance && !mayBeOcculted)
                            ? NotMeasuredReasons.DistanceToleranceTooHighForNonFullDisappearingOccultedStar
                            : NotMeasuredReasons.FWHMOutOfRange);
            }
            else
            {
                return(NotMeasuredReasons.MeasuredSuccessfully);
            }
        }
예제 #2
0
        internal NotMeasuredReasons DoLinearProfileFittingOfAveragedMoodelPhotometry(
            PSFFit fit,
            uint[,] matrix, int x0Int, int y0Int, float x0, float y0, float modelFWHM,
            float aperture, int matrixSize, bool useNumericalQadrature,
            bool isFullyDisappearingOccultedStar,
            uint[,] backgroundArea,
            bool mayBeOcculted /* Some magic based on a pure guess */,
            float bgAnnulusFactor,
            IBackgroundModelProvider backgroundModel)
        {
            double distance  = ImagePixel.ComputeDistance(fit.XCenter, x0, fit.YCenter, y0);
            double tolerance = isFullyDisappearingOccultedStar
                ? m_TimesHigherPositionToleranceForFullyOccultedStars * m_PositionTolerance
                : m_PositionTolerance;

            // We first go and do the measurement anyway
            if (fit.IsSolved)
            {
                SetPsfFitReading(fit, aperture, useNumericalQadrature, backgroundArea, bgAnnulusFactor, backgroundModel);
            }
            else
            {
                m_Aperture        = aperture;
                m_XCenter         = (float)fit.X0_Matrix;
                m_YCenter         = (float)fit.Y0_Matrix;
                m_TotalReading    = 0;
                m_TotalBackground = 0;
            }

            if (!fit.IsSolved ||                         // The PSF solution failed, mark the reading invalid
                (distance > tolerance && !mayBeOcculted) // If this doesn't look like a full disappearance, then make the reading invalid
                )
            {
                return(!fit.IsSolved
                                                ? NotMeasuredReasons.MeasurementPSFFittingFailed
                                                : NotMeasuredReasons.DistanceToleranceTooHighForNonFullDisappearingOccultedStar);
            }
            else
            {
                return(NotMeasuredReasons.MeasuredSuccessfully);
            }
        }
예제 #3
0
        internal NotMeasuredReasons DoOptimalExtractionPhotometry(
            PSFFit fit,
            uint[,] matrix, int x0Int, int y0Int, float x0, float y0,
            float aperture, int matrixSize, bool isFullyDisappearingOccultedStar,
            uint[,] backgroundArea,
            bool mayBeOcculted /* Some magic based on a pure guess */,
            double refinedFWHM, float bgAnnulusFactor)
        {
            // Proceed as with PSF Non linear, Then find the variance of the PSF fit and use a weight based on the residuals of the PSF fit
            // Signal[x, y] = PSF(x, y) + weight * Residual(x, y)


            double distance  = ImagePixel.ComputeDistance(fit.XCenter, x0, fit.YCenter, y0);
            double tolerance = isFullyDisappearingOccultedStar
                ? m_TimesHigherPositionToleranceForFullyOccultedStars * m_PositionTolerance
                : m_PositionTolerance;

            float psfBackground = (float)fit.I0;

            // almost like aperture
            if (matrix.GetLength(0) != 17 && matrix.GetLength(0) != 35)
            {
                throw new ApplicationException("Measurement error. Correlation: AFP-101B");
            }

            int   side     = matrix.GetLength(0);
            float halfSide = side * 1f / 2f;

            m_HasSaturatedPixels = false;
            m_PSFBackground      = double.NaN;
            m_FoundBestPSFFit    = null;
            m_XCenter            = x0 - x0Int + halfSide;
            m_YCenter            = y0 - y0Int + halfSide;
            m_Aperture           = aperture;
            m_PixelData          = matrix;

            m_TotalPixels = 0;

            double varR0Sq = fit.GetVariance();

            varR0Sq = varR0Sq * varR0Sq * 2;

            double deltaX = fit.X0_Matrix - m_XCenter;
            double deltaY = fit.Y0_Matrix - m_YCenter;

            m_TotalReading = GetReading(
                m_Aperture,
                m_PixelData, side, side,
                m_XCenter, m_YCenter,
                delegate(int x, int y)
            {
                double videoPixel = m_PixelData[x, y];
                double psfValue   = fit.GetValue(x + deltaX, y + deltaY);
                if (fit.UsesBackgroundModel)
                {
                    psfValue += fit.GetFittedBackgroundModelValue(x + deltaX, y + deltaY);
                }
                double residual = videoPixel - psfValue;

                double weight = Math.Exp(-residual * residual / varR0Sq);
                return(psfValue + residual * weight);
            },
                ref m_TotalPixels);

            if (m_TotalPixels > 0)
            {
                if (m_BackgroundMethod == TangraConfig.BackgroundMethod.PSFBackground)
                {
                    if (float.IsNaN(psfBackground))
                    {
                        m_TotalBackground = 0;
                    }
                    else
                    {
                        m_TotalBackground = (uint)Math.Round(m_TotalPixels * psfBackground);
                    }
                }
                else if (m_BackgroundMethod == TangraConfig.BackgroundMethod.Background3DPolynomial)
                {
                    if (!fit.UsesBackgroundModel)
                    {
                        throw new InvalidOperationException("3D-Polynomial was not applied correctly.");
                    }

                    m_TotalBackground = Integration.IntegrationOverCircularArea(
                        (x, y) => fit.GetFittedBackgroundModelValue(x, y),
                        m_Aperture);
                }
                else if (m_BackgroundMethod != TangraConfig.BackgroundMethod.PSFBackground)
                {
                    int    offset        = (35 - fit.MatrixSize) / 2;
                    double bgFromAnnulus = GetBackground(backgroundArea, m_Aperture, m_XCenter + offset, m_YCenter + offset, bgAnnulusFactor);
                    m_TotalBackground = (uint)Math.Round(m_TotalPixels * (float)bgFromAnnulus);
                }
                else
                {
                    throw new ApplicationException("Measurement error. Correlation: AFP-102B");
                }

                if (!fit.IsSolved ||                                                 // The PSF solution failed, mark the reading invalid
                    (distance > tolerance && !mayBeOcculted) ||                      // If this doesn't look like a full disappearance, then make the reading invalid
                    (fit.FWHM < 0.75 * refinedFWHM || fit.FWHM > 1.25 * refinedFWHM) // The FWHM is too small or too large, make the reading invalid
                    )
                {
                    return(!fit.IsSolved
                            ? NotMeasuredReasons.MeasurementPSFFittingFailed
                            : (distance > tolerance && !mayBeOcculted)
                                ? NotMeasuredReasons.DistanceToleranceTooHighForNonFullDisappearingOccultedStar
                                : NotMeasuredReasons.FWHMOutOfRange);
                }
            }
            else
            {
                // We can't do much here, but this should never happen (??)
                m_TotalBackground = 0;
                m_TotalReading    = 0;

                return(NotMeasuredReasons.NoPixelsToMeasure);
            }

            return(NotMeasuredReasons.MeasuredSuccessfully);
        }
예제 #4
0
        public NotMeasuredReasons MeasureObject(
            IImagePixel center,
            uint[,] data,
            uint[,] backgroundPixels,
            int bpp,
            TangraConfig.PreProcessingFilter filter,
            TangraConfig.PhotometryReductionMethod reductionMethod,
            TangraConfig.PsfQuadrature psfQuadrature,
            TangraConfig.PsfFittingMethod psfFittingMethod,
            float aperture,
            double refinedFWHM,
            float refinedAverageFWHM,
            IMeasurableObject measurableObject,
            IImagePixel[] objectsInGroup,
            float[] aperturesInGroup,
            bool fullDisappearance)
        {
            // NOTE: This is how the center of the pixel area passed in data and background arrays is determined
            // TODO: Pass the center as an argument
            int centerX = (int)Math.Round(center.XDouble);
            int centerY = (int)Math.Round(center.YDouble);

            float msrX0 = (float)center.XDouble;
            float msrY0 = (float)center.YDouble;

            float bgAnnulusFactor = 1;

            switch (filter)
            {
            case TangraConfig.PreProcessingFilter.LowPassFilter:
                data             = ImageFilters.LowPassFilter(data, bpp, true);
                backgroundPixels = ImageFilters.LowPassFilter(backgroundPixels, bpp, true);
                break;

            case TangraConfig.PreProcessingFilter.LowPassDifferenceFilter:
                data             = ImageFilters.LowPassDifferenceFilter(data, bpp, true);
                backgroundPixels = ImageFilters.LowPassDifferenceFilter(backgroundPixels, bpp, true);
                break;

            default:
                break;
            }

            float modelFWHM = float.NaN;

            if (psfFittingMethod == TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel)
            {
                if (TangraConfig.Settings.Photometry.UseUserSpecifiedFWHM)
                {
                    modelFWHM = TangraConfig.Settings.Photometry.UserSpecifiedFWHM;
                }
                else
                {
                    modelFWHM = refinedAverageFWHM;
                }
            }

            DoublePSFFit             doublefit       = null;
            PSFFit                   fit             = null;
            IBackgroundModelProvider backgroundModel = null;

            // 1 - Fit a PSF to the current obejct
            if (objectsInGroup != null && objectsInGroup.Length == 2)
            {
                // 1A - When this is a star group
                int x1 = (int)Math.Round((data.GetLength(0) / 2) + objectsInGroup[0].XDouble - center.XDouble);
                int y1 = (int)Math.Round((data.GetLength(0) / 2) + objectsInGroup[0].YDouble - center.YDouble);
                int x2 = (int)Math.Round((data.GetLength(0) / 2) + objectsInGroup[1].XDouble - center.XDouble);
                int y2 = (int)Math.Round((data.GetLength(0) / 2) + objectsInGroup[1].YDouble - center.YDouble);
                doublefit = new DoublePSFFit(centerX, centerY);

                if (psfFittingMethod == TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel &&
                    !float.IsNaN(modelFWHM))
                {
                    doublefit.FittingMethod = PSFFittingMethod.LinearFitOfAveragedModel;
                    doublefit.SetAveragedModelFWHM(modelFWHM);
                }

                doublefit.Fit(data, x1, y1, x2, y2);

                PSFFit star1 = doublefit.GetGaussian1();
                PSFFit star2 = doublefit.GetGaussian2();

                if (m_BackgroundMethod == TangraConfig.BackgroundMethod.Background3DPolynomial)
                {
                    var bg3dFit = new Background3DPolynomialFit();
                    bg3dFit.Fit(data, star1, star2);

                    doublefit.Fit(data, bg3dFit, x1, y1, x2, y2);

                    star1           = doublefit.GetGaussian1();
                    star2           = doublefit.GetGaussian2();
                    backgroundModel = bg3dFit;
                }

                double d1 = ImagePixel.ComputeDistance(measurableObject.Center.XDouble, doublefit.X1Center, measurableObject.Center.YDouble, doublefit.Y1Center);
                double d2 = ImagePixel.ComputeDistance(measurableObject.Center.XDouble, doublefit.X2Center, measurableObject.Center.YDouble, doublefit.Y2Center);

                fit = (d1 < d2) ? star1 : star2;

                if (reductionMethod == TangraConfig.PhotometryReductionMethod.AperturePhotometry)
                {
                    // NOTE: If aperture photometry is used, we measure the double object in a single larger aperture centered at the middle
                    double alpha = Math.Atan((star2.YCenter - star1.YCenter) / (star2.XCenter - star1.XCenter));

                    float dx = (float)((star1.FWHM - star2.FWHM) * Math.Cos(alpha));
                    float dy = (float)((star1.FWHM - star2.FWHM) * Math.Sin(alpha));

                    msrX0 = (float)(star1.XCenter - star1.FWHM + star2.XCenter + star2.FWHM) / 2.0f - dx;
                    msrY0 = (float)(star1.YCenter - star1.FWHM + star2.YCenter + star2.FWHM) / 2.0f - dy;

                    aperture        = aperturesInGroup.Sum();
                    bgAnnulusFactor = 0.67f;
                }
            }
            else if (reductionMethod != TangraConfig.PhotometryReductionMethod.AperturePhotometry)
            {
                // 1B - When this is a single star
                fit = new PSFFit(centerX, centerY);

                if (psfFittingMethod == TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel &&
                    !float.IsNaN(modelFWHM))
                {
                    fit.FittingMethod = PSFFittingMethod.LinearFitOfAveragedModel;
                    fit.SetAveragedModelFWHM(modelFWHM);
                }

                fit.Fit(data, measurableObject.PsfFittingMatrixSize);

                if (m_BackgroundMethod == TangraConfig.BackgroundMethod.Background3DPolynomial)
                {
                    // If 3D Poly Background is used then fit the background, and supply it to the PSF Fitting
                    var bg3dFit = new Background3DPolynomialFit();
                    bg3dFit.Fit(backgroundPixels, fit, null);

                    backgroundModel = bg3dFit;

                    if (psfFittingMethod != TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel)
                    {
                        /* 3D Poly modelling works in a direct fit only with non-linear fitting */
                        fit.Fit(backgroundPixels, bg3dFit, measurableObject.PsfFittingMatrixSize);
                    }
                }
            }
            else if (
                reductionMethod == TangraConfig.PhotometryReductionMethod.AperturePhotometry &&
                m_BackgroundMethod == TangraConfig.BackgroundMethod.Background3DPolynomial)
            {
                // 1C - Single star with aperture photometry and 3D Poly Background
                var bg3dFit = new Background3DPolynomialFit();
                bg3dFit.Fit(backgroundPixels, (float)(centerX - msrX0 + 17), (float)(centerY - msrY0 + 17), 2 * aperture);

                backgroundModel = bg3dFit;
            }

            // 2 - Do the actual photometric measurements (signal and background) based on the selected methods
            if (reductionMethod == TangraConfig.PhotometryReductionMethod.PsfPhotometry)
            {
                // 2A - PSF Photometry
                if (TangraConfig.Settings.Photometry.PsfFittingMethod == TangraConfig.PsfFittingMethod.DirectNonLinearFit)
                {
                    return(DoNonLinearProfileFittingPhotometry(
                               fit,
                               data, centerX, centerY, msrX0, msrY0,
                               aperture,
                               measurableObject.PsfFittingMatrixSize,
                               psfQuadrature == TangraConfig.PsfQuadrature.NumericalInAperture,
                               measurableObject.IsOccultedStar && fullDisappearance,
                               backgroundPixels,
                               measurableObject.MayHaveDisappeared,
                               refinedFWHM,
                               bgAnnulusFactor));
                }
                else if (psfFittingMethod == TangraConfig.PsfFittingMethod.LinearFitOfAveragedModel)
                {
                    return(DoLinearProfileFittingOfAveragedMoodelPhotometry(
                               fit,
                               data, centerX, centerY, msrX0, msrY0, modelFWHM,
                               aperture,
                               measurableObject.PsfFittingMatrixSize,
                               psfQuadrature == TangraConfig.PsfQuadrature.NumericalInAperture,
                               measurableObject.IsOccultedStar && fullDisappearance,
                               backgroundPixels,
                               measurableObject.MayHaveDisappeared,
                               bgAnnulusFactor, backgroundModel));
                }
                else
                {
                    throw new NotImplementedException();
                }
            }
            else if (reductionMethod == TangraConfig.PhotometryReductionMethod.AperturePhotometry)
            {
                return(DoAperturePhotometry(
                           data, centerX, centerY, msrX0, msrY0,
                           aperture,
                           measurableObject.PsfFittingMatrixSize,
                           backgroundPixels, bgAnnulusFactor, backgroundModel,
                           measurableObject.Center.X, measurableObject.Center.Y));
            }
            else if (reductionMethod == TangraConfig.PhotometryReductionMethod.OptimalExtraction)
            {
                return(DoOptimalExtractionPhotometry(
                           fit,
                           data, centerX, centerY, msrX0, msrY0,
                           aperture,
                           measurableObject.PsfFittingMatrixSize,
                           measurableObject.IsOccultedStar && fullDisappearance,
                           backgroundPixels,
                           measurableObject.MayHaveDisappeared,
                           refinedFWHM, bgAnnulusFactor));
            }
            else
            {
                throw new ArgumentOutOfRangeException("reductionMethod");
            }
        }