Example #1
0
        private string GetReductionMethodDisplayName(TangraConfig.PhotometryReductionMethod method)
        {
            switch (method)
            {
            case TangraConfig.PhotometryReductionMethod.AperturePhotometry:
                return("Aperture Photometry");

            case TangraConfig.PhotometryReductionMethod.OptimalExtraction:
                return("Optimal Extraction");

            case TangraConfig.PhotometryReductionMethod.PsfPhotometry:
                return("Numerical Psf Photometry");
            }

            return("N/A");
        }
Example #2
0
        private PhotometryReductionMethod ConvertSignalMethod(TangraConfig.PhotometryReductionMethod method)
        {
            switch (method)
            {
            case TangraConfig.PhotometryReductionMethod.AperturePhotometry:
                return(PhotometryReductionMethod.AperturePhotometry);

            case TangraConfig.PhotometryReductionMethod.PsfPhotometry:
                return(PhotometryReductionMethod.PsfPhotometry);

            case TangraConfig.PhotometryReductionMethod.OptimalExtraction:
                return(PhotometryReductionMethod.OptimalExtraction);

            default:
                return(PhotometryReductionMethod.Unknown);
            }
        }
Example #3
0
        public void SetComboboxIndexFromPhotometryReductionMethod(TangraConfig.PhotometryReductionMethod method)
        {
            switch (method)
            {
            case TangraConfig.PhotometryReductionMethod.AperturePhotometry:
                cbxReductionType.SelectedIndex = 0;
                break;

            case TangraConfig.PhotometryReductionMethod.PsfPhotometry:
                cbxReductionType.SelectedIndex = 1;
                break;

            case TangraConfig.PhotometryReductionMethod.OptimalExtraction:
                cbxReductionType.SelectedIndex = 2;
                break;
            }
        }
 private void SetMeasurementMethods()
 {
     if (cbMeaMethod.SelectedIndex == 0)
     {
         m_BackgroundMethod = TangraConfig.BackgroundMethod.BackgroundMedian;
         m_SignalMethod     = TangraConfig.PhotometryReductionMethod.AperturePhotometry;
     }
     else if (cbMeaMethod.SelectedIndex == 1)
     {
         m_BackgroundMethod = TangraConfig.BackgroundMethod.AverageBackground;
         m_SignalMethod     = TangraConfig.PhotometryReductionMethod.AperturePhotometry;
     }
     else if (cbMeaMethod.SelectedIndex == 2)
     {
         m_BackgroundMethod = TangraConfig.BackgroundMethod.BackgroundMode;
         m_SignalMethod     = TangraConfig.PhotometryReductionMethod.AperturePhotometry;
     }
     else if (cbMeaMethod.SelectedIndex == 3)
     {
         m_BackgroundMethod = TangraConfig.BackgroundMethod.PSFBackground;
         m_SignalMethod     = TangraConfig.PhotometryReductionMethod.PsfPhotometry;
     }
     else if (cbMeaMethod.SelectedIndex == 4)
     {
         m_BackgroundMethod = TangraConfig.BackgroundMethod.BackgroundMedian;
         m_SignalMethod     = TangraConfig.PhotometryReductionMethod.PsfPhotometry;
     }
     else if (cbMeaMethod.SelectedIndex == 5)
     {
         m_BackgroundMethod = TangraConfig.BackgroundMethod.AverageBackground;
         m_SignalMethod     = TangraConfig.PhotometryReductionMethod.PsfPhotometry;
     }
     else if (cbMeaMethod.SelectedIndex == 6)
     {
         m_BackgroundMethod = TangraConfig.BackgroundMethod.BackgroundMode;
         m_SignalMethod     = TangraConfig.PhotometryReductionMethod.PsfPhotometry;
     }
 }
 private NotMeasuredReasons MeasureObject(
     IImagePixel center,
     uint[,] data,
     uint[,] backgroundPixels,
     int bpp,
     MeasurementsHelper measurer,
     TangraConfig.PreProcessingFilter filter,
     TangraConfig.PhotometryReductionMethod reductionMethod,
     TangraConfig.PsfQuadrature psfQuadrature,
     TangraConfig.PsfFittingMethod psfFittngMethod,
     float aperture,
     double refinedFWHM,
     float refinedAverageFWHM,
     IMeasurableObject measurableObject,
     IImagePixel[] groupCenters,
     float[] aperturesInGroup,
     bool fullDisappearance
     )
 {
     return(measurer.MeasureObject(
                center, data, backgroundPixels, bpp, filter, reductionMethod, psfQuadrature, psfFittngMethod,
                aperture, refinedFWHM, refinedAverageFWHM, measurableObject, groupCenters, aperturesInGroup, fullDisappearance));
 }
Example #6
0
        public StarMagnitudeFit(
			AstroImage astroImage,
			int bitPix,
			List<double> intencities,
			List<double> magnitudes,
			List<double> colours,
			List<IStar> starNumbers,
			List<PSFFit> psfGaussians,
			List<double> profileFittedAmplitudes,
			List<bool> saturatedFlags,
			double a, double b, double c, float encodingGamma, TangraConfig.KnownCameraResponse reverseCameraResponse, int excludedStars,
			TangraConfig.PreProcessingFilter filter, double empericalFWHM, 
			TangraConfig.PhotometryReductionMethod photometryReductionMethod, 
			TangraConfig.BackgroundMethod photometryBackgroundMethod,
			TangraConfig.PsfQuadrature psfQuadrature,
			TangraConfig.PsfFittingMethod psfFittingMethod,
            MeasurementsHelper measurer,
            float? aperture)
        {
            m_CurrentAstroImage = astroImage;
            m_BitPix = bitPix;
            m_Intencities = intencities;
            m_Magnitudes = magnitudes;
            m_Colours = colours;
            m_Residuals = new List<double>();
            m_StarNumbers = starNumbers;
            m_PSFGaussians = psfGaussians;
            m_EncodingGamma = encodingGamma;
            m_ReverseCameraResponse = reverseCameraResponse;
            m_ExcludedStars = excludedStars;
            m_SaturatedFlags = saturatedFlags;
            m_ProfileFittedAmplitudes = profileFittedAmplitudes;

            m_Sigma = 0;
            for (int i = 0; i < intencities.Count; i++)
            {
                double computed = a * -2.5 * Math.Log10(intencities[i]) + b * colours[i] + c;
                double diff = Math.Abs(computed - magnitudes[i]);
                m_Residuals.Add(diff);

                m_Sigma += diff*diff;
            }
            m_Sigma = Math.Sqrt(m_Sigma / (m_Residuals.Count - 1));

            m_Filter = filter;
            m_EmpericalFWHM = empericalFWHM;
            m_PhotometryReductionMethod = photometryReductionMethod;
            m_PhotometryBackgroundMethod = photometryBackgroundMethod;
            m_PsfQuadrature = psfQuadrature;
            m_PsfFittingMethod = psfFittingMethod;

            m_A = a;
            m_B = b;
            m_C = c;

            m_Measurer = measurer.Clone();
            m_MeasurementAperture = aperture;

            m_Sigma = 0;
            m_MinRes = double.MaxValue;
            m_MaxRes = double.MinValue;
            m_MinMag = double.MaxValue;
            m_MaxMag = double.MinValue;
            for (int i = 0; i < m_Residuals.Count; i++)
            {
                double res = m_Residuals[i];

                m_Sigma += res * res;
                if (m_MinRes > res) m_MinRes = res;
                if (m_MaxRes < res) m_MaxRes = res;

                double mag = m_Magnitudes[i];
                if (m_MinMag > mag) m_MinMag = mag;
                if (m_MaxMag < mag) m_MaxMag = mag;
            }

            m_Sigma = Math.Sqrt(m_Sigma / m_Residuals.Count);
        }
Example #7
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);
        }
Example #8
0
        public StarMagnitudeFit(
            AstroImage astroImage,
            int bitPix,
            List <double> intencities,
            List <double> magnitudes,
            List <double> colours,
            List <IStar> starNumbers,
            List <PSFFit> psfGaussians,
            List <double> profileFittedAmplitudes,
            List <bool> saturatedFlags,
            double a, double b, double c, float encodingGamma, TangraConfig.KnownCameraResponse reverseCameraResponse, int excludedStars,
            TangraConfig.PreProcessingFilter filter, double empericalFWHM,
            TangraConfig.PhotometryReductionMethod photometryReductionMethod,
            TangraConfig.BackgroundMethod photometryBackgroundMethod,
            TangraConfig.PsfQuadrature psfQuadrature,
            TangraConfig.PsfFittingMethod psfFittingMethod,
            MeasurementsHelper measurer,
            float?aperture)
        {
            m_CurrentAstroImage       = astroImage;
            m_BitPix                  = bitPix;
            m_Intencities             = intencities;
            m_Magnitudes              = magnitudes;
            m_Colours                 = colours;
            m_Residuals               = new List <double>();
            m_StarNumbers             = starNumbers;
            m_PSFGaussians            = psfGaussians;
            m_EncodingGamma           = encodingGamma;
            m_ReverseCameraResponse   = reverseCameraResponse;
            m_ExcludedStars           = excludedStars;
            m_SaturatedFlags          = saturatedFlags;
            m_ProfileFittedAmplitudes = profileFittedAmplitudes;

            m_Sigma = 0;
            for (int i = 0; i < intencities.Count; i++)
            {
                double computed = a * -2.5 * Math.Log10(intencities[i]) + b * colours[i] + c;
                double diff     = Math.Abs(computed - magnitudes[i]);
                m_Residuals.Add(diff);

                m_Sigma += diff * diff;
            }
            m_Sigma = Math.Sqrt(m_Sigma / (m_Residuals.Count - 1));

            m_Filter                     = filter;
            m_EmpericalFWHM              = empericalFWHM;
            m_PhotometryReductionMethod  = photometryReductionMethod;
            m_PhotometryBackgroundMethod = photometryBackgroundMethod;
            m_PsfQuadrature              = psfQuadrature;
            m_PsfFittingMethod           = psfFittingMethod;

            m_A = a;
            m_B = b;
            m_C = c;

            m_Measurer            = measurer.Clone();
            m_MeasurementAperture = aperture;

            m_Sigma  = 0;
            m_MinRes = double.MaxValue;
            m_MaxRes = double.MinValue;
            m_MinMag = double.MaxValue;
            m_MaxMag = double.MinValue;
            for (int i = 0; i < m_Residuals.Count; i++)
            {
                double res = m_Residuals[i];

                m_Sigma += res * res;
                if (m_MinRes > res)
                {
                    m_MinRes = res;
                }
                if (m_MaxRes < res)
                {
                    m_MaxRes = res;
                }

                double mag = m_Magnitudes[i];
                if (m_MinMag > mag)
                {
                    m_MinMag = mag;
                }
                if (m_MaxMag < mag)
                {
                    m_MaxMag = mag;
                }
            }

            m_Sigma = Math.Sqrt(m_Sigma / m_Residuals.Count);
        }
Example #9
0
        public static StarMagnitudeFit PerformFit(
            IAstrometryController astrometryController,
            IVideoController videoController,
            int bitPix,
            uint maxSignalValue,
            FitInfo astrometricFit,
            TangraConfig.PhotometryReductionMethod photometryReductionMethod,
            TangraConfig.PsfQuadrature psfQuadrature,
            TangraConfig.PsfFittingMethod psfFittingMethod,
            TangraConfig.BackgroundMethod photometryBackgroundMethod,
            TangraConfig.PreProcessingFilter filter,
            List <IStar> catalogueStars,
            Guid magnitudeBandId,
            float encodingGamma,
            TangraConfig.KnownCameraResponse reverseCameraResponse,
            float?aperture,
            float?annulusInnerRadius,
            int?annulusMinPixels,
            ref float empericalPSFR0)
        {
            uint saturatedValue = TangraConfig.Settings.Photometry.Saturation.GetSaturationForBpp(bitPix, maxSignalValue);

            MeasurementsHelper measurer = new MeasurementsHelper(
                bitPix,
                photometryBackgroundMethod,
                TangraConfig.Settings.Photometry.SubPixelSquareSize,
                saturatedValue);

            measurer.SetCoreProperties(
                annulusInnerRadius ?? TangraConfig.Settings.Photometry.AnnulusInnerRadius,
                annulusMinPixels ?? TangraConfig.Settings.Photometry.AnnulusMinPixels,
                CorePhotometrySettings.Default.RejectionBackgroundPixelsStdDev,
                2 /* TODO: This must be configurable */);

            var bgProvider = new BackgroundProvider(videoController);

            measurer.GetImagePixelsCallback += new MeasurementsHelper.GetImagePixelsDelegate(bgProvider.measurer_GetImagePixelsCallback);

            List <double> intencities    = new List <double>();
            List <double> magnitudes     = new List <double>();
            List <double> colours        = new List <double>();
            List <double> residuals      = new List <double>();
            List <bool>   saturatedFlags = new List <bool>();
            List <IStar>  stars          = new List <IStar>();
            List <PSFFit> gaussians      = new List <PSFFit>();

            List <MagFitRecord> fitRecords = new List <MagFitRecord>();

            AstroImage currentAstroImage = videoController.GetCurrentAstroImage(false);
            Rectangle  osdRectToExclude  = astrometryController.OSDRectToExclude;
            Rectangle  rectToInclude     = astrometryController.RectToInclude;
            bool       limitByInclusion  = astrometryController.LimitByInclusion;

            int matSize = CorePhotometrySettings.Default.MatrixSizeForCalibratedPhotometry;

            double a             = double.NaN;
            double b             = double.NaN;
            double c             = double.NaN;
            int    excludedStars = 0;
            double empericalFWHM = double.NaN;

            try
            {
                foreach (PlateConstStarPair pair in astrometricFit.AllStarPairs)
                {
                    if (limitByInclusion && !rectToInclude.Contains((int)pair.x, (int)pair.y))
                    {
                        continue;
                    }
                    if (!limitByInclusion && osdRectToExclude.Contains((int)pair.x, (int)pair.y))
                    {
                        continue;
                    }

                    IStar star = catalogueStars.Find(s => s.StarNo == pair.StarNo);
                    if (star == null || double.IsNaN(star.Mag) || star.Mag == 0)
                    {
                        continue;
                    }

                    uint[,] data = currentAstroImage.GetMeasurableAreaPixels((int)pair.x, (int)pair.y, matSize);

                    PSFFit fit = new PSFFit((int)pair.x, (int)pair.y);
                    fit.Fit(data, PSF_FIT_AREA_SIZE);
                    if (!fit.IsSolved)
                    {
                        continue;
                    }

                    MagFitRecord record = new MagFitRecord();
                    record.Star       = star;
                    record.Pair       = pair;
                    record.PsfFit     = fit;
                    record.Saturation = IsSaturated(data, matSize, saturatedValue);

                    if (!EXCLUDE_SATURATED_STARS || !record.Saturation)
                    {
                        fitRecords.Add(record);
                    }
                }

                // We need the average R0 if it hasn't been determined yet
                if (float.IsNaN(empericalPSFR0))
                {
                    empericalPSFR0 = 0;
                    foreach (MagFitRecord rec in fitRecords)
                    {
                        empericalPSFR0 += (float)rec.PsfFit.R0;
                    }
                    empericalPSFR0 /= fitRecords.Count;
                }

                empericalFWHM = 2 * Math.Sqrt(Math.Log(2)) * empericalPSFR0;

                foreach (MagFitRecord record in fitRecords)
                {
                    ImagePixel center   = new ImagePixel(255, record.Pair.x, record.Pair.y);
                    int        areaSize = filter == TangraConfig.PreProcessingFilter.NoFilter ? 17 : 19;

                    int centerX = (int)Math.Round(center.XDouble);
                    int centerY = (int)Math.Round(center.YDouble);

                    uint[,] data             = currentAstroImage.GetMeasurableAreaPixels(centerX, centerY, areaSize);
                    uint[,] backgroundPixels = currentAstroImage.GetMeasurableAreaPixels(centerX, centerY, 35);

                    measurer.MeasureObject(
                        center,
                        data,
                        backgroundPixels,
                        currentAstroImage.Pixelmap.BitPixCamera,
                        filter,
                        photometryReductionMethod,
                        psfQuadrature,
                        psfFittingMethod,
                        aperture != null ? aperture.Value : (float)Aperture(record.PsfFit.FWHM),
                        record.PsfFit.FWHM,
                        (float)empericalFWHM,
                        new FakeIMeasuredObject(record.PsfFit),
                        null,
                        null,
                        false);

                    double intensity = measurer.TotalReading - measurer.TotalBackground;
                    if (intensity > 0)
                    {
                        var mag = record.Star.GetMagnitudeForBand(magnitudeBandId);
                        var clr = record.Star.MagJ - record.Star.MagK;

                        if (!double.IsNaN(mag) && !double.IsNaN(clr) && !double.IsInfinity(mag) && !double.IsInfinity(clr))
                        {
                            intencities.Add(intensity);
                            magnitudes.Add(record.Star.GetMagnitudeForBand(magnitudeBandId));
                            colours.Add(record.Star.MagJ - record.Star.MagK);

                            gaussians.Add(record.PsfFit);
                            stars.Add(record.Star);
                            saturatedFlags.Add(measurer.HasSaturatedPixels || record.PsfFit.IMax >= measurer.SaturationValue);
                        }
                    }
                }


                // Remove stars with unusual PSF fit radii (once only)
                double sum = 0;
                for (int i = 0; i < gaussians.Count; i++)
                {
                    sum += gaussians[i].R0;
                }
                double averageR = sum / gaussians.Count;

                residuals.Clear();
                sum = 0;
                for (int i = 0; i < gaussians.Count; i++)
                {
                    residuals.Add(averageR - gaussians[i].R0);
                    sum += (averageR - gaussians[i].R0) * (averageR - gaussians[i].R0);
                }
                double stdDev = Math.Sqrt(sum) / gaussians.Count;

                if (EXCLUDE_BAD_RESIDUALS)
                {
                    for (int i = residuals.Count - 1; i >= 0; i--)
                    {
                        if (Math.Abs(residuals[i]) > 6 * stdDev)
                        {
                            intencities.RemoveAt(i);
                            magnitudes.RemoveAt(i);
                            colours.RemoveAt(i);
                            stars.RemoveAt(i);
                            gaussians.RemoveAt(i);
                            saturatedFlags.RemoveAt(i);
                        }
                    }
                }

                double maxResidual = Math.Max(0.1, TangraConfig.Settings.Photometry.MaxResidualStellarMags);

                for (int itter = 1; itter <= MAX_ITERR; itter++)
                {
                    residuals.Clear();

                    SafeMatrix A = new SafeMatrix(intencities.Count, 3);
                    SafeMatrix X = new SafeMatrix(intencities.Count, 1);

                    int idx = 0;
                    for (int i = 0; i < intencities.Count; i++)
                    {
                        A[idx, 0] = magnitudes[i];
                        A[idx, 1] = colours[i];
                        A[idx, 2] = 1;

                        X[idx, 0] = -2.5 * Math.Log10(intencities[i]);

                        idx++;
                    }

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

                    double Ka = bx[0, 0];
                    double Kb = bx[1, 0];
                    double Kc = bx[2, 0];

                    // -2.5 * a * Log(Median-Intensity) = A * Mv + B * Mjk + C - b
                    // -2.5 * Log(Median-Intensity) = Ka * Mv + Kb * Mjk + Kc
                    // Mv = -2.5 * a * Log(Median-Intensity) - b * Mjk - c
                    a = 1 / Ka;
                    b = -Kb / Ka;
                    c = -Kc / Ka;

                    int starsExcludedThisTime = 0;

                    if (EXCLUDE_BAD_RESIDUALS)
                    {
                        List <int> indexesToRemove = new List <int>();
                        for (int i = 0; i < intencities.Count; i++)
                        {
                            double computed = a * -2.5 * Math.Log10(intencities[i]) + b * colours[i] + c;

                            double diff = Math.Abs(computed - magnitudes[i]);
                            if (itter < MAX_ITERR)
                            {
                                if (Math.Abs(diff) > maxResidual)
                                {
                                    indexesToRemove.Add(i);
                                }
                            }
                            else
                            {
                                residuals.Add(diff);
                            }
                        }


                        for (int i = indexesToRemove.Count - 1; i >= 0; i--)
                        {
                            int idxToRemove = indexesToRemove[i];
                            intencities.RemoveAt(idxToRemove);
                            magnitudes.RemoveAt(idxToRemove);
                            colours.RemoveAt(idxToRemove);
                            stars.RemoveAt(idxToRemove);
                            gaussians.RemoveAt(idxToRemove);
                            saturatedFlags.RemoveAt(idxToRemove);

                            excludedStars++;
                            starsExcludedThisTime++;
                        }
                    }

                    if (starsExcludedThisTime == 0)
                    {
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.ToString());
            }

            return(new StarMagnitudeFit(
                       currentAstroImage,
                       bitPix,
                       intencities, magnitudes, colours, stars, gaussians, new List <double>(),
                       saturatedFlags, a, b, c, encodingGamma, reverseCameraResponse, excludedStars, filter, empericalFWHM,
                       photometryReductionMethod, photometryBackgroundMethod, psfQuadrature, psfFittingMethod, measurer, aperture));
        }
Example #10
0
 private void SetMeasurementMethods()
 {
     if (cbMeaMethod.SelectedIndex == 0)
     {
         m_BackgroundMethod = TangraConfig.BackgroundMethod.BackgroundMedian;
         m_SignalMethod = TangraConfig.PhotometryReductionMethod. AperturePhotometry;
     }
     else if (cbMeaMethod.SelectedIndex == 1)
     {
         m_BackgroundMethod = TangraConfig.BackgroundMethod.AverageBackground;
         m_SignalMethod = TangraConfig.PhotometryReductionMethod.AperturePhotometry;
     }
     else if (cbMeaMethod.SelectedIndex == 2)
     {
         m_BackgroundMethod = TangraConfig.BackgroundMethod.BackgroundMode;
         m_SignalMethod = TangraConfig.PhotometryReductionMethod.AperturePhotometry;
     }
     else if (cbMeaMethod.SelectedIndex == 3)
     {
         m_BackgroundMethod = TangraConfig.BackgroundMethod.PSFBackground;
         m_SignalMethod = TangraConfig.PhotometryReductionMethod.PsfPhotometry;
     }
     else if (cbMeaMethod.SelectedIndex == 4)
     {
         m_BackgroundMethod = TangraConfig.BackgroundMethod.BackgroundMedian;
         m_SignalMethod = TangraConfig.PhotometryReductionMethod.PsfPhotometry;
     }
     else if (cbMeaMethod.SelectedIndex == 5)
     {
         m_BackgroundMethod = TangraConfig.BackgroundMethod.AverageBackground;
         m_SignalMethod = TangraConfig.PhotometryReductionMethod.PsfPhotometry;
     }
     else if (cbMeaMethod.SelectedIndex == 6)
     {
         m_BackgroundMethod = TangraConfig.BackgroundMethod.BackgroundMode;
         m_SignalMethod = TangraConfig.PhotometryReductionMethod.PsfPhotometry;
     }
 }
Example #11
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");
            }
        }