public static void PSFPhotometry(FitInfo astrometricFit, List <IStar> catalogueStars, AstroImage currentAstroImage, Rectangle osdRectToExclude, Rectangle rectToInclude, bool limitByInclusion) { StringBuilder output = new StringBuilder(); foreach (PlateConstStarPair pair in astrometricFit.AllStarPairs) { uint[,] data = currentAstroImage.GetMeasurableAreaPixels( (int)Math.Round(pair.x), (int)Math.Round(pair.y), 9); if (limitByInclusion && !rectToInclude.Contains((int)pair.x, (int)pair.y)) { continue; } if (!limitByInclusion && osdRectToExclude.Contains((int)pair.x, (int)pair.y)) { continue; } PSFFit gaussian = new PSFFit((int)Math.Round(pair.x), (int)Math.Round(pair.y)); gaussian.Fit(data); if (gaussian.IsSolved) { IStar star = catalogueStars.Find(s => s.StarNo == pair.StarNo); if (star != null && !double.IsNaN(star.MagR)) { output.AppendLine(string.Format("{0}, {1}, {2}, {3}, {4}", pair.StarNo, star.MagR, gaussian.R0, gaussian.IMax, gaussian.I0)); } } } File.WriteAllText(@"C:\PSF_Photo.csv", output.ToString()); }
public double GetIntencity(ImagePixel center, out bool isSaturated) { isSaturated = false; uint[,] data = m_CurrentAstroImage.GetMeasurableAreaPixels(center.X, center.Y, 17); PSFFit fit = new PSFFit(center.X, center.Y); fit.Fit(data, PSF_FIT_AREA_SIZE); if (!fit.IsSolved) { return(double.NaN); } int areaSize = m_Filter == TangraConfig.PreProcessingFilter.NoFilter ? 17 : 19; int centerX = (int)Math.Round(center.XDouble); int centerY = (int)Math.Round(center.YDouble); data = m_CurrentAstroImage.GetMeasurableAreaPixels(centerX, centerY, areaSize); uint[,] backgroundPixels = m_CurrentAstroImage.GetMeasurableAreaPixels(centerX, centerY, 35); m_Measurer.MeasureObject( center, data, backgroundPixels, m_CurrentAstroImage.Pixelmap.BitPixCamera, m_Filter, m_PhotometryReductionMethod, m_PsfQuadrature, m_PsfFittingMethod, m_MeasurementAperture ?? (float)Aperture(fit.FWHM), fit.FWHM, (float)m_EmpericalFWHM, new FakeIMeasuredObject(fit), null, null, false); isSaturated = m_Measurer.HasSaturatedPixels; return(m_Measurer.TotalReading - m_Measurer.TotalBackground); }
private void frmRunMultiFrameSpectroscopy_Load(object sender, EventArgs e) { IImagePixel starCenter = m_VideoOperation.SelectedStar; m_SpectraReader = new SpectraReader(m_AstroImage, m_VideoOperation.SelectedStarBestAngle, 1); m_Spectra = m_SpectraReader.ReadSpectra((float)starCenter.XDouble, (float)starCenter.YDouble, (int)nudAreaWing.Value, (int)nudBackgroundWing.Value, (int)nudBackgroundGap.Value, PixelCombineMethod.Average); m_Mapper = new RotationMapper(m_AstroImage.Width, m_AstroImage.Height, m_VideoOperation.SelectedStarBestAngle); uint[,] pixels = m_AstroImage.GetMeasurableAreaPixels(starCenter.X, starCenter.Y, 35); m_ZeroOrderPsf = new PSFFit(starCenter.X, starCenter.Y); m_ZeroOrderPsf.Fit(pixels); m_Spectra.ZeroOrderFWHM = (float)m_ZeroOrderPsf.FWHM; PlotMeasurementAreas(); PlotAlignTarget(); nudDivisor.SetNUDValue((decimal)m_AstroImage.Pixelmap.MaxSignalValue); nudMultiplier.Value = 1024; }
internal frmAddOrEditSingleTarget(int objectId, TrackedObjectConfig selectedObject, LCStateMachine state, VideoController videoController) { InitializeComponent(); m_VideoController = videoController; m_AutocenteredApertureAvailable = true; Text = "Edit Object"; btnAdd.Text = "Save"; btnDontAdd.Text = "Cancel"; btnDelete.Visible = true; m_IsEdit = true; m_ObjectId = objectId; m_State = state; m_AstroImage = m_State.VideoOperation.m_StackedAstroImage; ObjectToAdd = selectedObject; if (selectedObject.TrackingType != TrackingType.ComparisonStar) { nudFitMatrixSize.SetNUDValue(selectedObject.PsfFitMatrixSize); } m_Center = new ImagePixel( selectedObject.OriginalFieldCenterX, selectedObject.OriginalFieldCenterY); if (ObjectToAdd.PositionTolerance > 0) { nudPositionTolerance.SetNUDValue((decimal)ObjectToAdd.PositionTolerance); } Initialize(); if (!selectedObject.IsWeakSignalObject && !selectedObject.IsFixedAperture) { int matrixSize = selectedObject.PsfFitMatrixSize; GetFitInMatrix(selectedObject.Gaussian, ref matrixSize, selectedObject.ApertureInPixels); selectedObject.PsfFitMatrixSize = matrixSize; } else { m_ProcessingPixels = m_AstroImage.GetMeasurableAreaPixels(m_Center); m_DisplayPixels = m_AstroImage.GetMeasurableAreaDisplayBitmapPixels(m_Center); m_FWHM = 6; m_Gaussian = null; m_X0 = selectedObject.ApertureMatrixX0; m_Y0 = selectedObject.ApertureMatrixY0; dx = selectedObject.ApertureDX; dy = selectedObject.ApertureDY; PlotSingleTargetPixels(); nudAperture1.SetNUDValue((decimal)Math.Round(ObjectToAdd.ApertureInPixels, 2)); } SetHeightAndType(); if (selectedObject.TrackingType == TrackingType.GuidingStar) { SelectedObjectType = TrackingType.GuidingStar; } else if (selectedObject.TrackingType == TrackingType.OccultedStar) { SelectedObjectType = TrackingType.OccultedStar; } }
private bool GetFitInMatrix(ITrackedObjectPsfFit gaussian, ref int matirxSize, float preselectedAperture) { rbGuidingStar.Text = "Guiding/Comparison Star"; m_IsBrightEnoughForAutoGuidingStar = false; if (m_Aperture == null) { if (gaussian != null && !double.IsNaN(gaussian.FWHM) && TangraConfig.Settings.Photometry.SignalApertureUnitDefault == TangraConfig.SignalApertureUnit.FWHM) { m_Aperture = (float)(gaussian.FWHM * TangraConfig.Settings.Photometry.DefaultSignalAperture); } else { m_Aperture = (float)(TangraConfig.Settings.Photometry.DefaultSignalAperture); } } else if ( gaussian != null && !double.IsNaN(gaussian.FWHM) && TangraConfig.Settings.Photometry.SignalApertureUnitDefault == TangraConfig.SignalApertureUnit.FWHM && m_Aperture < (float)(gaussian.FWHM * TangraConfig.Settings.Photometry.DefaultSignalAperture)) { m_Aperture = (float)(gaussian.FWHM * TangraConfig.Settings.Photometry.DefaultSignalAperture); } nudFitMatrixSize.ValueChanged -= nudFitMatrixSize_ValueChanged; try { uint[,] autoStarsPixels = m_AstroImage.GetMeasurableAreaPixels(m_Center.X, m_Center.Y, 35); m_AutoStarsInLargerArea = StarFinder.GetStarsInArea( ref autoStarsPixels, m_AstroImage.Pixelmap.BitPixCamera, m_AstroImage.Pixelmap.MaxSignalValue, m_AstroImage.MedianNoise, LightCurveReductionContext.Instance.DigitalFilter); m_ProcessingPixels = ImageFilters.CutArrayEdges(autoStarsPixels, 9); m_DisplayPixels = m_AstroImage.GetMeasurableAreaDisplayBitmapPixels(m_Center.X, m_Center.Y, 17); m_AutoStarsInArea = new List <PSFFit>(); foreach (PSFFit autoStar in m_AutoStarsInLargerArea) { if (autoStar.XCenter > 9 && autoStar.XCenter < 9 + 17 && autoStar.YCenter > 9 && autoStar.YCenter < 9 + 17) { // Don't change original star so use a clone PSFFit clone = autoStar.Clone(); clone.SetNewFieldCenterFrom35PixMatrix(8, 8); m_AutoStarsInArea.Add(clone); } } int oldMatirxSize = matirxSize; if (m_AutoStarsInArea.Count == 0) { rbGuidingStar.Text = "Guiding/Comparison Star"; // There are no stars that are bright enough. Simply let the user do what they want, but still try to default to a sensible aperture size MeasurementsHelper measurement = ReduceLightCurveOperation.DoConfiguredMeasurement(m_ProcessingPixels, m_Aperture.Value, m_AstroImage.Pixelmap.BitPixCamera, m_AstroImage.Pixelmap.MaxSignalValue, 3.0, ref matirxSize); if (measurement.FoundBestPSFFit != null && measurement.FoundBestPSFFit.IsSolved && measurement.FoundBestPSFFit.Certainty > 0.1) { m_X0 = measurement.XCenter; m_Y0 = measurement.YCenter; m_FWHM = (float)measurement.FoundBestPSFFit.FWHM; } else { m_X0 = 8; m_Y0 = 8; m_FWHM = 6; } m_Gaussian = null; nudFitMatrixSize.SetNUDValue(11); } else if (m_AutoStarsInArea.Count == 1) { // There is exactly one good star found. Go and do a fit in a wider area double bestFindTolerance = 3.0; for (int i = 0; i < 2; i++) { MeasurementsHelper measurement = ReduceLightCurveOperation.DoConfiguredMeasurement(m_ProcessingPixels, m_Aperture.Value, m_AstroImage.Pixelmap.BitPixCamera, m_AstroImage.Pixelmap.MaxSignalValue, bestFindTolerance, ref matirxSize); if (measurement != null && matirxSize != -1) { if (matirxSize < 5) { // Do a centroid in the full area, and get another matix centered at the centroid ImagePixel centroid = new ImagePixel(m_Center.X, m_Center.Y); m_ProcessingPixels = m_AstroImage.GetMeasurableAreaPixels(centroid); m_DisplayPixels = m_AstroImage.GetMeasurableAreaDisplayBitmapPixels(centroid); m_X0 = centroid.X; m_Y0 = centroid.Y; m_FWHM = 6; m_Gaussian = null; nudFitMatrixSize.SetNUDValue(11); } else { m_X0 = measurement.XCenter; m_Y0 = measurement.YCenter; if (measurement.FoundBestPSFFit != null) { m_FWHM = (float)measurement.FoundBestPSFFit.FWHM; m_Gaussian = measurement.FoundBestPSFFit; } else { m_FWHM = 6; m_Gaussian = null; } m_ProcessingPixels = measurement.PixelData; nudFitMatrixSize.SetNUDValue(matirxSize); } } else { matirxSize = oldMatirxSize; return(false); } if (m_Gaussian != null) { if (IsBrightEnoughtForGuidingStar()) { rbGuidingStar.Text = "Guiding/Comparison Star"; m_IsBrightEnoughForAutoGuidingStar = true; } break; } } } else if (m_AutoStarsInArea.Count > 1) { rbGuidingStar.Text = "Guiding/Comparison Star"; // There are more stars found. double xBest = m_Gaussian != null ? m_Gaussian.XCenter : m_IsEdit ? ObjectToAdd.ApertureMatrixX0 : 8.5; double yBest = m_Gaussian != null ? m_Gaussian.YCenter : m_IsEdit ? ObjectToAdd.ApertureMatrixY0 : 8.5; // by default use the one closest to the original location PSFFit closestFit = m_AutoStarsInArea[0]; double closestDist = double.MaxValue; foreach (PSFFit star in m_AutoStarsInArea) { double dist = Math.Sqrt((star.XCenter - xBest) * (star.XCenter - xBest) + (star.YCenter - yBest) * (star.YCenter - yBest)); if (closestDist > dist) { closestDist = dist; closestFit = star; } } m_X0 = (float)closestFit.XCenter; m_Y0 = (float)closestFit.YCenter; m_FWHM = (float)closestFit.FWHM; m_Gaussian = closestFit; nudFitMatrixSize.SetNUDValue(m_IsEdit ? ObjectToAdd.PsfFitMatrixSize : closestFit.MatrixSize); } //if (m_Gaussian == null && gaussian.Certainty > 0.1 && ImagePixel.ComputeDistance(gaussian.X0_Matrix, 8, gaussian.Y0_Matrix, 8) < 3) //{ // // Id we failed to locate a bright enough autostar, but the default Gaussian is still certain enough and close enought to the center, we present it as a starting point // m_X0 = (float)gaussian.X0_Matrix; // m_Y0 = (float)gaussian.Y0_Matrix; // m_FWHM = (float)gaussian.FWHM; // m_Gaussian = gaussian; //} decimal appVal; if (float.IsNaN(preselectedAperture)) { if (float.IsNaN(m_Aperture.Value)) { appVal = Convert.ToDecimal(TangraConfig.Settings.Photometry.DefaultSignalAperture); } else { appVal = Convert.ToDecimal(m_Aperture.Value); if (nudAperture1.Maximum < appVal) { nudAperture1.Maximum = appVal + 1; } } } else { appVal = (decimal)preselectedAperture; } if ((float)appVal > m_Aperture) { m_Aperture = (float)appVal; } nudAperture1.SetNUDValue(Math.Round(appVal, 2)); PlotSingleTargetPixels(); PlotGaussian(); return(true); } finally { nudFitMatrixSize.ValueChanged += nudFitMatrixSize_ValueChanged; } }
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); } } }
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 Initialise() { picTarget1Pixels.Image = new Bitmap(AREA_SIDE * MAGN_FACTOR, AREA_SIDE * MAGN_FACTOR, PixelFormat.Format24bppRgb); picTarget1PSF.Image = new Bitmap(picTarget1PSF.Width, picTarget1PSF.Height); m_AllTargetColors = new Color[] { TangraConfig.Settings.Color.Target1, TangraConfig.Settings.Color.Target2, TangraConfig.Settings.Color.Target3, TangraConfig.Settings.Color.Target4 }; m_Color = m_AllTargetColors[m_ObjectId]; if (m_ObjectId < 3 && !m_IsEdit) { m_Color2 = m_AllTargetColors[m_ObjectId + 1]; } bool doubleModeDisabled = false; if (m_IsEdit && m_ObjectId2 <= 3) { m_Color2 = m_AllTargetColors[m_ObjectId2]; } else if (m_ObjectId == 3 || m_ObjectId2 == 4) { doubleModeDisabled = true; rbTwoObjects.Enabled = false; } m_Pen = new Pen(m_Color); m_Brush = new SolidBrush(m_Color); m_Pen2 = new Pen(m_Color2); m_Brush2 = new SolidBrush(m_Color2); m_ProcessingPixels = m_AstroImage.GetMeasurableAreaPixels(m_Center.X, m_Center.Y, 35); m_DisplayPixels = m_AstroImage.GetMeasurableAreaDisplayBitmapPixels(m_Center.X, m_Center.Y, 35); ImagePixel newCenter = null; bool autoDoubleObjectLocated = m_TryAutoDoubleFind && TryAutoLocateDoubleObject(out newCenter); if (autoDoubleObjectLocated) { int deltaX = (int)Math.Round(newCenter.XDouble - 18); int deltaY = (int)Math.Round(newCenter.YDouble - 18); m_X1Start -= deltaX; m_Y1Start -= deltaY; m_X2Start -= deltaX; m_Y2Start -= deltaY; m_Center = new ImagePixel(newCenter.Brightness, m_Center.XDouble + newCenter.XDouble - 18, m_Center.YDouble + newCenter.YDouble - 18); m_ProcessingPixels = m_AstroImage.GetMeasurableAreaPixels(m_Center.X, m_Center.Y, 35); m_DisplayPixels = m_AstroImage.GetMeasurableAreaDisplayBitmapPixels(m_Center.X, m_Center.Y, 35); m_AutoDoubleCenter = new ImagePixel(m_Center); m_AutoDoubleX1Start = m_X1Start; m_AutoDoubleY1Start = m_Y1Start; m_AutoDoubleX2Start = m_X2Start; m_AutoDoubleY2Start = m_Y2Start; } bool occultedStartAlreadyPicked = m_State.MeasuringStars.Any(x => x.IsOcultedStar()); if (m_IsEdit) { rbOcculted.Enabled = m_EditingOccultedStar || !occultedStartAlreadyPicked; rbReference.Checked = !m_EditingOccultedStar; rbOcculted.Checked = m_EditingOccultedStar; } else { if (occultedStartAlreadyPicked) { rbOcculted.Enabled = false; rbReference.Checked = true; } else { rbOcculted.Enabled = true; rbOcculted.Checked = true; } } if (doubleModeDisabled || !autoDoubleObjectLocated) { rbOneObject.Checked = true; } UpdateStateControls(); DrawCollorPanel(); DrawCollorPanel2(); CalculatePSF(); }
public uint[,] measurer_GetImagePixelsCallback(int x, int y, int matrixSize) { AstroImage currentAstroImage = m_VideoController.GetCurrentAstroImage(false); return(currentAstroImage.GetMeasurableAreaPixels(x, y, matrixSize)); }
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)); }