private void GenerateFrame(Pixelmap pixmap, List<IStar> stars, ModelConfig modelConfig)
        {
            var mea = new MeasurementsHelper(
                pixmap.BitPixCamera,
                TangraConfig.BackgroundMethod.BackgroundMedian,
                TangraConfig.Settings.Photometry.SubPixelSquareSize,
                TangraConfig.Settings.Photometry.Saturation.GetSaturationForBpp(pixmap.BitPixCamera, pixmap.MaxSignalValue));

            float apertureSize = APERTURE;
            float annulusInnerRadius = (GAP + APERTURE) / APERTURE;
            int annulusMinPixels = (int)(Math.PI * (Math.Pow(ANNULUS + GAP + APERTURE, 2) - Math.Pow(GAP + APERTURE, 2)));

            mea.SetCoreProperties(annulusInnerRadius, annulusMinPixels, CorePhotometrySettings.Default.RejectionBackgroundPixelsStdDev, 2 /* TODO: This must be configurable */);

            var measurements = new Dictionary<IStar, double>();

            foreach (IStar star in stars)
            {
                double x, y;

                GetOnPlateCoordinates(star.RADeg, star.DEDeg, modelConfig, out x, out y);

                if (x < 0 || x > modelConfig.FrameWidth || y < 0 || y > modelConfig.FrameHeight)
                    continue;

                float starMag = GetStarMag(star, modelConfig.PhotometricFilter);
                float iMax = ModelStarAmplitude(star, starMag, modelConfig, pixmap.BitPixCamera, pixmap.MaxSignalValue);

                if (!float.IsNaN(iMax))
                {
                    VideoModelUtils.GenerateStar(pixmap, (float)x, (float)y, (float)modelConfig.FWHM, iMax, 0 /*Use Gaussian */);

                    if (modelConfig.CheckMagnitudes)
                    {
                        var image = new AstroImage(pixmap);
                        uint[,] data = image.GetMeasurableAreaPixels((int)x, (int)y, 17);
                        uint[,] backgroundPixels = image.GetMeasurableAreaPixels((int)x, (int)y, 35);

                        PSFFit fit = new PSFFit((int)x, (int)y);
                        fit.Fit(data);

                        var result = mea.MeasureObject(new ImagePixel(x, y), data, backgroundPixels, pixmap.BitPixCamera,
                            TangraConfig.PreProcessingFilter.NoFilter,
                            TangraConfig.PhotometryReductionMethod.AperturePhotometry, TangraConfig.PsfQuadrature.NumericalInAperture,
                            TangraConfig.PsfFittingMethod.DirectNonLinearFit,
                            apertureSize, modelConfig.FWHM, (float)modelConfig.FWHM,
                            new FakeIMeasuredObject(fit),
                            null, null,
                            false);

                        if (result == NotMeasuredReasons.TrackedSuccessfully && !mea.HasSaturatedPixels)
                        {
                            // Add value for fitting
                            measurements.Add(star, mea.TotalReading - mea.TotalBackground);
                        }
                    }
                }
            }

            if (modelConfig.CheckMagnitudes)
                CalculateGagnitudeFit(measurements, modelConfig.BVSlope);
        }
        private void InitStarAmplitudeModelling(ModelConfig modelConfig, float accuracy, int bitPix, uint maxSignalValue)
        {
            if (m_MagnitudeToPeakDict != null)
                return;

            m_MagnitudeToPeakDict = new Dictionary<double, int>();
            m_MagnitudeToPeakMags = new List<double>();
            m_MagnitudeToPeakPeaks = new List<int>();

            var mea = new MeasurementsHelper(
                bitPix,
                TangraConfig.BackgroundMethod.BackgroundMedian,
                TangraConfig.Settings.Photometry.SubPixelSquareSize,
                TangraConfig.Settings.Photometry.Saturation.GetSaturationForBpp(bitPix, maxSignalValue));

            float apertureSize = APERTURE;
            float annulusInnerRadius = (GAP + APERTURE) / APERTURE;
            int annulusMinPixels = (int)(Math.PI * (Math.Pow(ANNULUS + GAP + APERTURE, 2) - Math.Pow(GAP + APERTURE, 2)));

            mea.SetCoreProperties(annulusInnerRadius, annulusMinPixels, CorePhotometrySettings.Default.RejectionBackgroundPixelsStdDev, 2 /* TODO: This must be configurable */);

            int peak = (int)(maxSignalValue - (modelConfig.NoiseMean + modelConfig.DarkFrameMean) * modelConfig.Integration);
            int TOTAL_STEPS = 100;
            double step = Math.Log10(peak) / TOTAL_STEPS;
            double zeroMag = double.NaN;
            for (int ii = 0; ii < TOTAL_STEPS; ii++)
            {
                int amplitude = (int)Math.Round(Math.Pow(10, Math.Log10(peak) - ii * step));
                Pixelmap pixmap = new Pixelmap(64, 64, bitPix, new uint[64 * 64], null, null);
                VideoModelUtils.GenerateStar(pixmap, 32, 32, (float)modelConfig.FWHM, amplitude, 0 /* Gaussian */);
                PSFFit fit = new PSFFit(32, 32);
                AstroImage img = new AstroImage(pixmap);
                uint[,] data = img.GetMeasurableAreaPixels(32, 32, 17);
                uint[,] backgroundPixels = img.GetMeasurableAreaPixels(32, 32, 35);

                fit.Fit(data);

                var result = mea.MeasureObject(new ImagePixel(32, 32), data, backgroundPixels, pixmap.BitPixCamera,
                    TangraConfig.PreProcessingFilter.NoFilter,
                    TangraConfig.PhotometryReductionMethod.AperturePhotometry, TangraConfig.PsfQuadrature.NumericalInAperture,
                    TangraConfig.PsfFittingMethod.DirectNonLinearFit,
                    apertureSize, modelConfig.FWHM, (float)modelConfig.FWHM,
                    new FakeIMeasuredObject(fit),
                    null, null,
                    false);

                if (result == NotMeasuredReasons.TrackedSuccessfully && !mea.HasSaturatedPixels)
                {
                    // Add value for fitting
                    double measurement = mea.TotalReading - mea.TotalBackground;
                    if (double.IsNaN(zeroMag))
                        zeroMag = modelConfig.BrighestUnsaturatedStarMag + 2.5 * Math.Log10(measurement);
                    double magnitude = -2.5 * Math.Log10(measurement) + zeroMag;

                    m_MagnitudeToPeakDict[magnitude] = amplitude;
                    m_MagnitudeToPeakMags.Add(magnitude);
                    m_MagnitudeToPeakPeaks.Add(amplitude);
                }
            }
        }
Example #3
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);
        }
        public static MeasurementsHelper DoConfiguredMeasurement(uint[,] matrix, float aperture, int bitPixCamera, uint maxSignalValue, double bestFindTolerance, ref int matrixSize)
        {
            var measurer = new MeasurementsHelper(
                            bitPixCamera,
                            TangraConfig.BackgroundMethod.BackgroundMedian /* We always use Background Median for configuration measurements. */,
                            TangraConfig.Settings.Photometry.SubPixelSquareSize,
                            TangraConfig.Settings.Photometry.Saturation.GetSaturationForBpp(bitPixCamera, maxSignalValue));

            measurer.SetCoreProperties(
                    TangraConfig.Settings.Photometry.AnnulusInnerRadius,
                    TangraConfig.Settings.Photometry.AnnulusMinPixels,
                    TangraConfig.Settings.Special.RejectionBackgroundPixelsStdDev,
                    4.0f);

            measurer.BestMatrixSizeDistanceDifferenceTolerance = bestFindTolerance;

            MeasurementsHelper.Filter measurementFilter = MeasurementsHelper.Filter.None;

            switch (LightCurveReductionContext.Instance.DigitalFilter)
            {
                case TangraConfig.PreProcessingFilter.NoFilter:
                    measurementFilter = MeasurementsHelper.Filter.None;
                    break;

                case TangraConfig.PreProcessingFilter.LowPassFilter:
                    measurementFilter = MeasurementsHelper.Filter.LP;
                    break;

                case TangraConfig.PreProcessingFilter.LowPassDifferenceFilter:
                    measurementFilter = MeasurementsHelper.Filter.LPD;
                    break;
            }

            // This will also find the best PSFFit
            measurer.FindBestFit(9, 9, measurementFilter, matrix, bitPixCamera, ref matrixSize, false);

            return measurer;
        }
        private void EnsureMeasurer(float positionTolerance)
        {
            m_Measurer = new MeasurementsHelper(
                                m_VideoController.VideoBitPix,
                                LightCurveReductionContext.Instance.NoiseMethod,
                                TangraConfig.Settings.Photometry.SubPixelSquareSize,
                                TangraConfig.Settings.Photometry.Saturation.GetSaturationForBpp(m_VideoController.VideoBitPix, m_VideoController.VideoAav16NormVal));

            m_Measurer.SetCoreProperties(
                TangraConfig.Settings.Photometry.AnnulusInnerRadius,
                TangraConfig.Settings.Photometry.AnnulusMinPixels,
                TangraConfig.PhotometrySettings.REJECTION_BACKGROUND_PIXELS_STD_DEV,
                positionTolerance);
        }
Example #6
0
        private void Worker(object state)
        {
            bool useLowPassDiff = Context.Filter == LightCurveContext.FilterType.LowPassDifference;
            bool useLowPass = Context.Filter == LightCurveContext.FilterType.LowPass;

            LightCurveController.ReloadAllReadingsFromLcFile();

            MeasurementsHelper measurer = new MeasurementsHelper(
                 Context.BitPix,
                 Context.BackgroundMethod,
                 TangraConfig.Settings.Photometry.SubPixelSquareSize,
                 TangraConfig.Settings.Photometry.Saturation.GetSaturationForBpp(Context.BitPix, Context.MaxPixelValue));

            measurer.SetCoreProperties(
                TangraConfig.Settings.Photometry.AnnulusInnerRadius,
                TangraConfig.Settings.Photometry.AnnulusMinPixels,
                TangraConfig.PhotometrySettings.REJECTION_BACKGROUND_PIXELS_STD_DEV,
                Header.PositionTolerance);

            m_EllapsedTime.Start();

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

            int refreshCount = m_RefreshProgressEveryHowManyItems;

            List<LCMeasurement> readings0 = Context.AllReadings[0];
            List<LCMeasurement> readings1 = Header.ObjectCount > 1 ? Context.AllReadings[1] : null;
            List<LCMeasurement> readings2 = Header.ObjectCount > 2 ? Context.AllReadings[2] : null;
            List<LCMeasurement> readings3 = Header.ObjectCount > 3 ? Context.AllReadings[3] : null;

            int processedCount = 0;

            for (int i = 0; i < readings0.Count; i++)
            {
                List<LCMeasurement> units = new List<LCMeasurement>();
                units.Add(readings0[i]);
                if (Header.ObjectCount > 1) units.Add(readings1[i]);
                if (Header.ObjectCount > 2) units.Add(readings2[i]);
                if (Header.ObjectCount > 3) units.Add(readings3[i]);

                if (m_CancelExecution)
                {
                    Invoke(new MethodInvoker(Cancelled));
                    return;
                }

                ProcessSingleUnitSet(units, useLowPass, useLowPassDiff, measurer);

                readings0[i] = units[0];
                if (Header.ObjectCount > 1) readings1[i] = units[1];
                if (Header.ObjectCount > 2) readings2[i] = units[2];
                if (Header.ObjectCount > 3) readings3[i] = units[3];

                processedCount++;

                if (processedCount % refreshCount == 0)
                {
                    Invoke(new ProgressDelegate(OnProgress), 0, processedCount);
                    if (Header.ObjectCount > 1) Invoke(new ProgressDelegate(OnProgress), 1, processedCount);
                    if (Header.ObjectCount > 2) Invoke(new ProgressDelegate(OnProgress), 2, processedCount);
                    if (Header.ObjectCount > 3) Invoke(new ProgressDelegate(OnProgress), 3, processedCount);
                }
            }

            Invoke(new MethodInvoker(Done));
        }
        private void EnsureMeasurer(float positionTolerance)
        {
            uint saturatedValue = TangraConfig.Settings.Photometry.Saturation.GetSaturationForBpp(m_VideoController.VideoBitPix, m_VideoController.VideoAav16NormVal);

            m_Measurer = new MeasurementsHelper(
                                m_VideoController.VideoBitPix,
                                m_BackgroundMethod,
                                TangraConfig.Settings.Photometry.SubPixelSquareSize,
                                saturatedValue);

            m_Measurer.SetCoreProperties(
                TangraConfig.Settings.Photometry.AnnulusInnerRadius,
                TangraConfig.Settings.Photometry.AnnulusMinPixels,
                TangraConfig.PhotometrySettings.REJECTION_BACKGROUND_PIXELS_STD_DEV,
                positionTolerance);

            m_Measurer.GetImagePixelsCallback += m_Measurer_GetImagePixelsCallback;
        }