private void CalculateAndDisplayBackground(uint[,] backgroundPixels)
        {
            if (backgroundPixels != null)
            {
                int bgWidth  = backgroundPixels.GetLength(0);
                int bgHeight = backgroundPixels.GetLength(1);

                var bgPixels = new List <uint>();

                for (int x = 0; x < bgWidth; x++)
                {
                    for (int y = 0; y < bgHeight; y++)
                    {
                        if (m_PSFFit == null || !m_PSFFit.IsSolved ||
                            ImagePixel.ComputeDistance(m_PSFFit.XCenter, x + bgWidth - m_PSFFit.MatrixSize, m_PSFFit.YCenter, y + bgHeight - m_PSFFit.MatrixSize) > 3 * m_PSFFit.FWHM)
                        {
                            bgPixels.Add(backgroundPixels[x, y]);
                        }
                    }
                }

                bgPixels.Sort();
                double background = 0;
                if (bgPixels.Count > 1)
                {
                    background = m_Bpp < 12
                                                ? bgPixels[bgPixels.Count / 2] // for 8 bit videos Median background works better
                                                : bgPixels.Average(x => x);    // for 12+bit videos average background works better
                }

                double residualsSquareSum = 0;
                foreach (uint bgPixel in bgPixels)
                {
                    residualsSquareSum += (background - bgPixel) * (background - bgPixel);
                }
                double noise = Math.Sqrt(residualsSquareSum / (bgPixels.Count - 1));

                lblBackground.Text = background.ToString("0.0");
                lblNoise.Text      = noise.ToString("0.0");

                if (m_PSFFit != null)
                {
                    double snr = m_PSFFit.GetSNR();
                    lblSNR.Text = snr.ToString("0.0");
                }
                else
                {
                    lblSNR.Text = "N/A";
                }

                if (m_PSFFit != null)
                {
                    lblFitVariance.Text = m_PSFFit.GetVariance().ToString("0.0");
                    lblFWHM.Text        = m_PSFFit.FWHM.ToString("0.0");
                }
                else
                {
                    lblFitVariance.Text = "N/A";
                    lblFWHM.Text        = "N/A";
                }
            }
            else
            {
                lblBackground.Text = "N/A";
                lblNoise.Text      = "N/A";
                lblSNR.Text        = "N/A";
            }
        }
Beispiel #2
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);
        }