public void Test12BitData() { string DATA_SER = "EQAAABEAAABqAQAAkAEAABgBAACuAQAAnQEAAMgBAABfAQAAbQEAALYBAAAJAQAAcAEAACMBAAA5AQAAWAEAAFMBAADVAQAAkQEAAFABAAAbAQAAYgEAAFwBAABTAQAAMgEAAH8BAABSAQAA1AEAAGoBAAC6AQAAnAEAAN4BAACKAQAAswEAAKUBAABhAQAAvwEAAE0BAABLAQAA9QAAAIoBAABWAQAAkwEAAOwBAACCAQAAxQEAAJYBAAD1AQAApgEAAPcBAACuAQAAawEAAEgBAAAZAQAAXAEAAF4BAAD0AQAA1QEAAH8BAADbAQAARwEAALkBAAAhAgAASgIAAMMBAAANAgAApgEAAGgBAAAWAQAADQEAAB4BAABiAQAAagEAABsBAABYAQAAuQEAAPgBAACgAgAAdgIAAMsCAAAKAwAABQMAALkCAAD9AQAAdgEAAKABAABoAQAAdwEAAD4BAABqAQAAaAEAAKUBAAC2AQAApgEAAFgDAACAAwAA6gMAALgEAACbBAAAMwMAAMMCAAAEAgAAoAEAAJYBAAAyAQAAWQEAADkBAABbAQAAdgEAAHwBAACpAQAAewIAACcEAABiBQAATgYAAL8FAABIBAAAkgMAALkBAAClAQAA2wEAANgAAAB8AQAAfAEAAO8AAABEAQAAjgEAAPcBAABEAgAASAMAAE0FAABLBgAADwYAACoEAAArAwAAugEAAEsBAACfAQAAfwEAABgBAABSAQAALQEAABABAADVAQAAWwEAANIBAACOAgAA8AMAANIFAAAuBQAAUwMAACQCAADaAQAAogEAAKMBAABFAQAA/gAAALMBAABNAQAAAQEAAG4BAAAyAQAAcwEAAE8CAAC8AgAA0wMAANoDAADDAgAAGgIAAOUBAAC/AQAAUwEAADUBAACsAQAADwEAACEBAADxAAAAYgEAABABAACrAQAApgEAANcBAAD6AQAAwwIAABACAABtAQAAEAEAAF4BAAB0AQAAWAEAAA8BAABkAQAAzwAAAD4BAABuAQAABgEAAOsBAACjAQAA9wAAAJEBAABiAQAAOwEAAJcBAADxAAAAXwEAAIsBAACvAQAAQQEAAGoBAABFAQAAeQEAALMBAAApAQAAbgEAAFYBAABtAQAA5gEAAJEBAAAkAQAA3gAAADMBAACzAQAAEwEAABkBAABLAQAAQQEAAE0BAACvAAAAzAAAACkBAABeAQAADwEAAFMBAACIAQAAUgEAANIBAACjAQAAEwEAADgBAAD+AAAAMwEAAEEBAAAqAQAAPAEAAF8BAABnAQAAdwEAAGoBAAAAAQAAOAEAAKUBAAAMAQAArAAAAAEBAABlAQAA4wAAADMBAACiAQAAHgEAACkBAAAqAQAAGAEAACcBAAADAQAAlwEAAEIBAAA8AQAA3gAAADMBAACoAQAAegEAAGEBAAApAQAAlgEAAHwBAABZAQAAIQEAAGIBAADaAAAAPgEAADIBAAA/AQAAZwEAAIoBAAA5AQAAywAAAGoBAACBAQAAIQEAAEgBAAA8AQAA"; uint[,] data = DATA_SER.FromBase64String(); int width = data.GetLength(0); int height = data.GetLength(1); int MAX = 255; uint[,] data_8bit = new uint[width,height]; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { data_8bit[x, y] = (uint)Math.Max(0, Math.Min(MAX, Math.Round(data[x, y] * MAX * 1.0f / 4095))); } } PSFFit.DataRange = PSFFittingDataRange.DataRange12Bit; var psfFit8bit = new PSFFit(100, 100); psfFit8bit.Fit(data_8bit); Console.WriteLine(string.Format("8Bit: ({0}, {1})", psfFit8bit.XCenter, psfFit8bit.YCenter)); PSFFit.DataRange = PSFFittingDataRange.DataRange12Bit; var psfFit = new PSFFit(100, 100); psfFit.Fit(data); Console.WriteLine(string.Format("12Bit: ({0}, {1})", psfFit.XCenter, psfFit.YCenter)); Assert.AreEqual(psfFit8bit.XCenter, psfFit.XCenter, 0.01); Assert.AreEqual(psfFit8bit.YCenter, psfFit.YCenter, 0.01); }
public frmTargetPSFViewerForm(VideoController videoController) { InitializeComponent(); m_VideoController = videoController; m_PSFFit = null; cbMeaMethod.SelectedIndex = 0; }
public ObjectClickEventArgs(ImagePixel pixel, PSFFit gausian, Point location, bool shiftHeld, bool ctrlHeld, MouseEventArgs mouseEventArgs) { ClickLocation = location; Pixel = pixel; Gausian = gausian; Shift = shiftHeld; Control = ctrlHeld; MouseEventArgs = mouseEventArgs; }
public void SetTrackedObjectMatch(PSFFit psfFitMatched) { PSFFit = psfFitMatched; Center = new ImagePixel((int)psfFitMatched.IMax, psfFitMatched.XCenter, psfFitMatched.YCenter); IsLocated = true; NotMeasuredReasons = NotMeasuredReasons.TrackedSuccessfully; if (PSFFit != null && PSFFit.IsSolved) { LastKnownGoodPosition = new ImagePixel(Center.Brightness, Center.XDouble, Center.YDouble); LastKnownGoodPsfCertainty = PSFFit.Certainty; } }
private void TrackSingleStar(int frameNo, IAstroImage astroImage) { TrackedStar.NewFrame(); float expectedX; float expectedY; GetExpectedXY(out expectedX, out expectedY); uint[,] pixels = astroImage.GetPixelsArea((int)expectedX, (int)expectedY, FIT_AREA); // There is only one object in the area, just do a wide fit followed by a fit with the selected matrix size PSFFit gaussian = new PSFFit((int)expectedX, (int)expectedY); gaussian.Fit(pixels, FIT_AREA); IImagePixel firstCenter = new ImagePixel((int)gaussian.XCenter, (int)gaussian.YCenter); pixels = astroImage.GetPixelsArea(firstCenter.X, firstCenter.Y, FIT_AREA); gaussian = new PSFFit(firstCenter.X, firstCenter.Y); gaussian.Fit(pixels, TrackedStar.PsfFitMatrixSize); if (gaussian.IsSolved) { TrackedStar.PSFFit = gaussian; TrackedStar.ThisFrameX = (float)gaussian.XCenter; TrackedStar.ThisFrameY = (float)gaussian.YCenter; TrackedStar.ThisSignalLevel = (float)(gaussian.IMax - gaussian.I0); TrackedStar.ThisFrameCertainty = (float)gaussian.Certainty; TrackedStar.SetIsLocated(true, NotMeasuredReasons.TrackedSuccessfully); } else { TrackedStar.ThisFrameX = expectedX; TrackedStar.ThisFrameY = expectedY; TrackedStar.ThisFrameCertainty = (float)gaussian.Certainty; Trace.WriteLine(string.Format("Frame {0}: Cannot confirm target {1} [SingleStar]. Cannot solve second PSF", m_FrameNo, TrackedStar.TargetNo)); TrackedStar.SetIsLocated(false, NotMeasuredReasons.PSFFittingFailed); } }
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 PlotAperturePreview() { if (m_MeasurementContext.ObjectToMeasure != null) { float x0 = m_MeasurementContext.ObjectToMeasure.X0; float y0 = m_MeasurementContext.ObjectToMeasure.Y0; // x0 and y0 were measured on the first frame but we may have moved to a different frame due to positioning to the first frame of integration period // so we determine the position of the object on the current frame in order to draw the aperture nicely centered var fit = new PSFFit((int)x0, (int)y0); fit.Fit(m_VideoController.GetCurrentAstroImage(false).GetMeasurableAreaPixels((int)x0, (int)y0)); if (fit.IsSolved) { x0 = (float)fit.XCenter; y0 = (float)fit.YCenter; } byte[,] bmpPixels = m_VideoController.GetCurrentAstroImage(false).GetMeasurableAreaDisplayBitmapPixels((int) x0, (int) y0, 85); Bitmap bmp = Pixelmap.ConstructBitmapFromBitmapPixels(bmpPixels, 85, 85); using (Graphics g = Graphics.FromImage(pboxAperturePreview.Image)) { g.DrawImage(bmp, 0, 0); float xCenter = (x0 - (int)x0) + 42; float yCenter = (y0 - (int)y0) + 42; float radius = (float) nudAperture.Value; g.DrawEllipse(Pens.YellowGreen, xCenter - radius, yCenter - radius, 2 * radius, 2 * radius); radius = (float)(nudAperture.Value + nudGap.Value); g.DrawEllipse(Pens.YellowGreen, xCenter - radius, yCenter - radius, 2 * radius, 2 * radius); radius = (float)(nudAperture.Value + nudGap.Value + nudAnnulus.Value); g.DrawEllipse(Pens.YellowGreen, xCenter - radius, yCenter - radius, 2 * radius, 2 * radius); g.Save(); } pboxAperturePreview.Invalidate(); } }
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()); }
internal void SetRefinedSignalLevel(PSFFit gaussian) { RefinedSignalLevel = (float)(gaussian.IMax - gaussian.I0); }
public static double DistanceTo(this PSFFit psf1, PSFFit psf2) { return Math.Sqrt(Math.Pow(psf1.XCenter - psf2.XCenter, 2) + Math.Pow(psf1.YCenter - psf2.YCenter, 2)); }
private void LocateFullDisappearingObject(IAstroImage astroImage, TrackedObject trackedObject, IImagePixel newStaringPos) { if (m_Refining) // Full disapearance is not expected during refining LocateNonGuidingObject(astroImage, trackedObject, newStaringPos); else { double averageX, averageY; GetAverageObjectPositionsFromGuidingStars(trackedObject, newStaringPos, out averageX, out averageY); trackedObject.ThisFrameX = (float)averageX + 0.5f; trackedObject.ThisFrameY = (float)averageY + 0.5f; trackedObject.PSFFit = null; trackedObject.ThisSignalLevel = float.NaN; trackedObject.ThisFrameCertainty = 1; int x0 = (int) Math.Round(averageX); int y0 = (int) Math.Round(averageY); trackedObject.SetIsLocated(false, NotMeasuredReasons.UnknownReason); PSFFit gaussian = null; int smallestMatrixSize = (int)Math.Round(trackedObject.OriginalObject.ApertureInPixels * 2); if (smallestMatrixSize % 2 == 0) smallestMatrixSize++; // If this is not an aperture photometry we still derive a PSF uint[,] pixels = astroImage.GetPixelsArea(x0, y0, 17); for (int i = trackedObject.PsfFitMatrixSize; i >= smallestMatrixSize; i -= 2) { int borderZeroes = (trackedObject.PsfFitMatrixSize - i) / 2; for (int x = 0; x < pixels.GetLength(0); x++) { for (int y = 0; y < borderZeroes; y++) { pixels[x, y] = 0; pixels[x, pixels.GetLength(1) - y - 1] = 0; } } for (int y = 0; y < pixels.GetLength(1); y++) { for (int x = 0; x < borderZeroes; x++) { pixels[x, y] = 0; pixels[pixels.GetLength(0) - x - 1, y] = 0; } } gaussian = new PSFFit(x0, y0); gaussian.Fit(pixels, trackedObject.PsfFitMatrixSize); if (gaussian.IsSolved) { double dist = ImagePixel.ComputeDistance((float)gaussian.XCenter, (float)averageX, (float)gaussian.YCenter, (float)averageY); if (dist <= PositionTolerance) { trackedObject.SetIsLocated(true, NotMeasuredReasons.TrackedSuccessfully); break; } else trackedObject.SetIsLocated(false, NotMeasuredReasons.FoundObjectNotWithInExpectedPositionTolerance); } else trackedObject.SetIsLocated(false, NotMeasuredReasons.PSFFittingFailed); } if (gaussian != null) { if (!trackedObject.IsLocated) trackedObject.SetIsLocated(true, NotMeasuredReasons.FullyDisappearingStarMarkedTrackedWithoutBeingFound); trackedObject.PSFFit = gaussian; trackedObject.ThisSignalLevel = (float)(gaussian.IMax - gaussian.I0); trackedObject.ThisFrameX = (float)gaussian.XCenter; trackedObject.ThisFrameY = (float)gaussian.YCenter; trackedObject.ThisFrameCertainty = (float)gaussian.Certainty; } } }
public override void MouseClick(ObjectClickEventArgs e) { if (m_OperationState == SpectroscopyState.ChoosingStar && e.Gausian != null && e.Gausian.IsSolved && e.Gausian.Certainty > 0.2) { float bestAngle = m_SpectroscopyController.LocateSpectraAngle(e.Gausian); if (float.IsNaN(bestAngle)) { SelectedStar = new ImagePixel(e.Gausian.XCenter, e.Gausian.YCenter); SelectedStarFWHM = e.Gausian.FWHM; m_SelectedStarGaussian = e.Gausian; MeasurementAreaWing = (int)(2 * Math.Ceiling(SelectedStarFWHM)); BackgroundAreaWing = MeasurementAreaWing; BackgroundAreaGap = 5; SelectedAnglePoint = Point.Empty; m_ControlPanel.ClearSpectra(); m_OperationState = SpectroscopyState.ChoosingAngleManually; } else { SelectedStar = new ImagePixel(e.Gausian.XCenter, e.Gausian.YCenter); SelectedStarFWHM = e.Gausian.FWHM; m_SelectedStarGaussian = e.Gausian; MeasurementAreaWing = (int)(2 * Math.Ceiling(SelectedStarFWHM)); BackgroundAreaWing = MeasurementAreaWing; BackgroundAreaGap = 5; SetBestAngle(bestAngle); } m_VideoController.RedrawCurrentFrame(false, true); } else if (m_OperationState == SpectroscopyState.ChoosingAngleManually && SelectedStar != null) { double atanAgnle = 180 * Math.Atan((SelectedStar.YDouble - e.Pixel.YDouble)/(e.Pixel.XDouble - SelectedStar.XDouble)) / Math.PI; if (atanAgnle < 0) atanAgnle = 360 + atanAgnle; int roughAngle = (int) atanAgnle; float bestAngle = m_SpectroscopyController.LocateSpectraAngle(e.Gausian, roughAngle); if (!float.IsNaN(bestAngle)) { SetBestAngle(bestAngle); m_VideoController.RedrawCurrentFrame(false, true); } } }
public void NextFrame(int frameNo, IAstroImage astroImage) { m_IsTrackedSuccessfully = false; StarMap starMap = new StarMap(); starMap.FindBestMap( m_StarMapConfig, (AstroImage)astroImage, Rectangle.Empty, new Rectangle(0, 0, astroImage.Width, astroImage.Height), AstrometryContext.Current.LimitByInclusion); if (starMap.Features.Count >= 5) { starMap.Features.Sort((x, y) => y.PixelCount.CompareTo(x.PixelCount)); int featuresToConsider = Math.Min(10, starMap.Features.Count); var featureDistances = new List<List<double>>(); for (int i = 0; i < featuresToConsider; i++) { var dist = new List<double>(); for (int j = 0; j < featuresToConsider; j++) dist.Add(double.NaN); featureDistances.Add(dist); } var pivotDistances = new List<List<double>>(); for (int i = 0; i < featuresToConsider; i++) pivotDistances.Add(new List<double>(UNINITIALIZED_DISTANCES)); for (int i = 0; i < featuresToConsider; i++) { var feature_i = starMap.Features[i]; for (int j = i + 1; j < featuresToConsider; j++) { var feature_j = starMap.Features[j]; double distance = feature_j.GetCenter().DistanceTo(feature_i.GetCenter()); pivotDistances[i][j] = distance; pivotDistances[j][i] = distance; } } Dictionary<int, int> pivotMap = IdentifyPivots(pivotDistances); int identifiedObjects = 0; for (int i = 0; i < m_TrackedObjects.Count; i++) { ((TrackedObject)m_TrackedObjects[i]).NewFrame(); var xVals = new List<double>(); var yVals = new List<double>(); foreach (int key in pivotMap.Keys) { int mapsToSourceFeatureId = pivotMap[key]; xVals.Add(starMap.Features[key].GetCenter().XDouble + m_TrackedObjectsPivotDistancesX[i][mapsToSourceFeatureId]); yVals.Add(starMap.Features[key].GetCenter().YDouble + m_TrackedObjectsPivotDistancesY[i][mapsToSourceFeatureId]); } double x0 = xVals.Median(); double y0 = yVals.Median(); double sigmaX = Math.Sqrt(xVals.Select(x => (x - x0)*(x - x0)).Sum()) / (xVals.Count - 1); double sigmaY = Math.Sqrt(yVals.Select(y => (y - y0)*(y - y0)).Sum()) / (yVals.Count - 1); if (!double.IsNaN(x0) && !double.IsNaN(y0) && xVals.Count > 1 && (sigmaX > m_FWHMAverage || sigmaY > m_FWHMAverage)) { // Some of the pivots may have been misidentified. Remove all entries with too large residuals and try again xVals.RemoveAll(x => Math.Abs(x - x0) > sigmaX); yVals.RemoveAll(y => Math.Abs(y - y0) > sigmaY); if (xVals.Count > 1) { x0 = xVals.Median(); y0 = yVals.Median(); sigmaX = Math.Sqrt(xVals.Select(x => (x - x0) * (x - x0)).Sum()) / (xVals.Count - 1); sigmaY = Math.Sqrt(yVals.Select(y => (y - y0) * (y - y0)).Sum()) / (yVals.Count - 1); } } if (!double.IsNaN(x0) && !double.IsNaN(y0) && xVals.Count > 1 && (sigmaX > m_FWHMAverage || sigmaY > m_FWHMAverage)) { // There is something really wrong about this. Reject the position and fail the frame m_TrackedObjects[i].SetIsTracked(false, NotMeasuredReasons.FoundObjectNotWithInExpectedPositionTolerance, null, null); } else { PSFFit fit = new PSFFit((int)x0, (int)y0); uint[,] data = ((AstroImage)astroImage).GetMeasurableAreaPixels((int)x0, (int)y0); fit.Fit(data); if (fit.IsSolved) { m_TrackedObjects[i].SetIsTracked(true, NotMeasuredReasons.TrackedSuccessfully, new ImagePixel(fit.XCenter, fit.YCenter), fit.Certainty); ((TrackedObject)m_TrackedObjects[i]).ThisFrameX = (float)fit.XCenter; ((TrackedObject)m_TrackedObjects[i]).ThisFrameY = (float)fit.YCenter; ((TrackedObjectBase)m_TrackedObjects[i]).PSFFit = fit; identifiedObjects++; } else { m_TrackedObjects[i].SetIsTracked(false, NotMeasuredReasons.PSFFittingFailed, null, null); } } } m_IsTrackedSuccessfully = identifiedObjects == m_TrackedObjects.Count; if (m_IsTrackedSuccessfully) UpdatePivotDistances(starMap, pivotMap); } }
public bool InitializeNewTracking(IAstroImage astroImage) { m_StarMapConfig = new StarMapInternalConfig(StarMapInternalConfig.Default); m_StarMapConfig.CustomMaxSignalValue = astroImage.GetPixelmapPixels().Max(); m_StarMapConfig.CustomOptimumStarsValue = 25; m_StarMapConfig.IsFITSFile = true; StarMap starMap = new StarMap(); starMap.FindBestMap( m_StarMapConfig, (AstroImage)astroImage, Rectangle.Empty, new Rectangle(0, 0, astroImage.Width, astroImage.Height), AstrometryContext.Current.LimitByInclusion); if (starMap.Features.Count < 10) { MessageBox.Show("Cannot initialize object tracking as less than 10 stars can be identified in the field"); return false; } // Build a signature of the largest 10 features (pivots) m_PivotDistances.Clear(); for (int i = 0; i < 10; i++) m_PivotDistances.Add(new List<double>(UNINITIALIZED_DISTANCES)); double fwhmSum = 0; int fwhmCount = 0; starMap.Features.Sort((x, y) => y.PixelCount.CompareTo(x.PixelCount)); for (int i = 0; i < 10; i++) { var feature_i = starMap.Features[i]; for (int j = i + 1; j < 10; j++) { var feature_j = starMap.Features[j]; double distance = feature_j.GetCenter().DistanceTo(feature_i.GetCenter()); m_PivotDistances[i][j] = distance; m_PivotDistances[j][i] = distance; } int x0 = feature_i.GetCenter().X; int y0 = feature_i.GetCenter().Y; PSFFit fit = new PSFFit((int) x0, (int) y0); uint[,] data = ((AstroImage) astroImage).GetMeasurableAreaPixels((int) x0, (int) y0); fit.Fit(data); if (fit.IsSolved) { fwhmSum += fit.FWHM; fwhmCount++; } } m_FWHMAverage = (float)(fwhmSum / fwhmCount); for (int i = 0; i < m_TrackedObjects.Count; i++) { m_TrackedObjectsPivotDistancesX[i] = new List<double>(); m_TrackedObjectsPivotDistancesY[i] = new List<double>(); for (int j = 0; j < 10; j++) { m_TrackedObjectsPivotDistancesX[i].Add(m_TrackedObjects[i].Center.XDouble - starMap.Features[j].GetCenter().XDouble); m_TrackedObjectsPivotDistancesY[i].Add(m_TrackedObjects[i].Center.YDouble - starMap.Features[j].GetCenter().YDouble); } int x0 = m_TrackedObjects[i].Center.X; int y0 = m_TrackedObjects[i].Center.Y; PSFFit fit = new PSFFit((int)x0, (int)y0); uint[,] data = ((AstroImage)astroImage).GetMeasurableAreaPixels((int)x0, (int)y0); fit.Fit(data); if (fit.IsSolved) { SetTargetFWHM(i, (float)fit.FWHM); } } m_TargetPivotDistancesListX.Clear(); m_TargetPivotDistancesListY.Clear(); return true; }
internal void SelectStar(PlateConstStarPair selectedPair, PSFFit psfFit) { if (selectedPair != null) { lblStarNo.Text = selectedPair.StarNo.ToString(); lblRA.Text = AstroConvert.ToStringValue(selectedPair.RADeg / 15.0, "HH MM SS.TT"); lblDE.Text = AstroConvert.ToStringValue(selectedPair.DEDeg, "+DD MM SS.T"); lblX.Text = selectedPair.x.ToString("0.00"); lblY.Text = selectedPair.y.ToString("0.00"); lblResRA.Text = string.Format("{0}\"", selectedPair.FitInfo.ResidualRAArcSec.ToString("0.00")); lblResDE.Text = string.Format("{0}\"", selectedPair.FitInfo.ResidualDEArcSec.ToString("0.00")); m_SelectedPSF = psfFit; } else { m_SelectedPSF = null; } pnlSelectedStar.Visible = selectedPair != null; }
protected PSFFit GetBestFitGaussian(AstroImage astroImage, TrackedObject guidingStar) { // Try all fits from 5 to 15. Find the one with the highest peak, then do a fit around this area with the configured psf matrix size uint[,] pixels = astroImage.GetMeasurableAreaPixels((int)guidingStar.LastFrameX, (int)guidingStar.LastFrameY); PSFFit bestGaussian = null; if (!guidingStar.OriginalObject.IsCloseToOtherStars) { // There is only one object in the area, just do a whide fit followed by a fit with the selected matrix size PSFFit gaussian = new PSFFit((int) guidingStar.LastFrameX, (int) guidingStar.LastFrameY); gaussian.Fit(pixels, pixels.GetLength(0)); if (gaussian.IsSolved) { bestGaussian = gaussian; } } else { // There is more than one object in the area. We need a smarter way to find the one we need. if (guidingStar.IsOccultedStar) { for (int matSize = 5; matSize < 15; matSize += 2) { PSFFit gaussian = new PSFFit((int) guidingStar.LastFrameX, (int) guidingStar.LastFrameY); gaussian.Fit(pixels, matSize); if (gaussian.IsSolved) { if (bestGaussian == null || bestGaussian.IMax < gaussian.IMax) { bestGaussian = gaussian; } } } } else { PSFFit gaussian = new PSFFit((int) guidingStar.LastFrameX, (int) guidingStar.LastFrameY); gaussian.Fit(pixels, guidingStar.PsfFitMatrixSize); } } if (bestGaussian != null) { pixels = astroImage.GetMeasurableAreaPixels((int)bestGaussian.XCenter, (int)bestGaussian.YCenter); bestGaussian = new PSFFit((int)bestGaussian.XCenter, (int)bestGaussian.YCenter); bestGaussian.Fit(pixels, guidingStar.PsfFitMatrixSize); } return bestGaussian; }
private void CheckAndCorrectGuidingStarPositions(IAstroImage astroImage, bool retryWithLPFilterIfSuspectObjects) { List<int> goodObjects = new List<int>(); List<int> suspectObjects = new List<int>(); for (int k = 0; k < 2; k++) { goodObjects.Clear(); suspectObjects.Clear(); if (LocateFirstObjects.Count == 1) { if (!LocateFirstObjects[0].IsLocated || float.IsNaN(LocateFirstObjects[0].ThisFrameX) || float.IsNaN(LocateFirstObjects[0].ThisFrameY)) { suspectObjects.Add(LocateFirstObjects[0].TargetNo); } } else { // See how many of the distances are okay for (int i = 0; i < LocateFirstObjects.Count; i++) { TrackedObject obj1 = LocateFirstObjects[i]; for (int j = 0; j < LocateFirstObjects.Count; j++) { if (i == j) continue; TrackedObject obj2 = LocateFirstObjects[j]; long pairId = (((long) obj1.TargetNo) << 32) + (long) obj2.TargetNo; double expectedDistance = m_RefinedDistances[pairId]; double actualDistance = ImagePixel.ComputeDistance(obj1.ThisFrameX, obj2.ThisFrameX, obj1.ThisFrameY, obj2.ThisFrameY); if (Math.Abs(expectedDistance - actualDistance) <= PositionTolerance) { goodObjects.Add(obj1.TargetNo); goodObjects.Add(obj2.TargetNo); } else { suspectObjects.Add(obj1.TargetNo); suspectObjects.Add(obj2.TargetNo); } } } } if (k == 0 && suspectObjects.Count > 0 && retryWithLPFilterIfSuspectObjects) { // There are some suspect objects. Try to locate the guiding stars with a low pass filter foreach (TrackedObject trackedObject in LocateFirstObjects) LocateObjectAsGuidingStar(astroImage, trackedObject, true); } else break; } if (suspectObjects.Count > 0) { if (goodObjects.Distinct().Count() == LocateFirstObjectsTargetIds.Count) { // There is at least one good distance involving each of the locate first objects // This means the suspect distance it not too bad so we ignore and continue } else { if (goodObjects.Count == 0) { List<TrackedObject> okayObjects = LocateFirstObjects.FindAll(o => !o.IsOccultedStar && o.IsLocated); if (okayObjects.Count == 0) { // If one of the objects is the occulted star (found) and non of the other guiding stars are found // then make all objects not found and use the latest expected positions foreach(TrackedObject obj in LocateFirstObjects) { obj.PSFFit = null; obj.ThisFrameX = obj.LastFrameX; obj.ThisFrameY = obj.LastFrameY; obj.ThisFrameCertainty = (float)obj.LastKnownGoodPsfCertainty; obj.SetIsLocated(false, NotMeasuredReasons.FitSuspectAsNoGuidingStarsAreLocated); } m_AllGuidingStarsFailed = true; return; } // If no distances are okay consider the brightest located first object as the correctly identified one // and then find the positions of the other ones based on the expected distances (and do another PSF fit in a smaller area) okayObjects = LocateFirstObjects.FindAll(o => o.IsLocated); okayObjects.Sort((o1, o2) => o1.LastSignalLevel.CompareTo(o2.LastSignalLevel)); TrackedObject brightestObject = okayObjects[0]; foreach (TrackedObject obj in LocateFirstObjects) { if (obj.TargetNo == brightestObject.TargetNo) continue; LocationVector vec = brightestObject.OtherGuidingStarsLocationVectors[obj.TargetNo]; double expectedX = brightestObject.ThisFrameX + vec.DeltaXToAdd; double expectedY = brightestObject.ThisFrameY + vec.DeltaYToAdd; if (expectedX < RefinedAverageFWHM || expectedX > astroImage.Width - RefinedAverageFWHM || expectedY < RefinedAverageFWHM || expectedY > astroImage.Height - RefinedAverageFWHM) { // The expected position in Off Screen. obj.PSFFit = null; obj.ThisFrameX = float.NaN; obj.ThisFrameY = float.NaN; obj.ThisFrameCertainty = float.NaN; obj.SetIsLocated(false, NotMeasuredReasons.ObjectExpectedPositionIsOffScreen); continue; } uint[,] pixels = astroImage.GetPixelsArea((int)Math.Round(expectedX), (int)Math.Round(expectedY), 19); pixels = EnhanceByteAreaForSearch(pixels); PSFFit gaussian = new PSFFit((int)Math.Round(expectedX), (int)Math.Round(expectedY)); gaussian.Fit(pixels, obj.PsfFitMatrixSize); if (gaussian.IsSolved) { double distance = ImagePixel.ComputeDistance(gaussian.XCenter, expectedX, gaussian.YCenter, expectedY); if (distance <= 2 * PositionTolerance) { // Object successfully located obj.PSFFit = gaussian; obj.ThisFrameX = (float)gaussian.XCenter; obj.ThisFrameY = (float)gaussian.YCenter; obj.ThisFrameCertainty = (float)gaussian.Certainty; obj.SetIsLocated(true, NotMeasuredReasons.TrackedSuccessfullyAfterDistanceCheck); Trace.WriteLine(string.Format("Frame {0}: Successfully located object #{1} after a close look up {2}px from the expected position.", m_FrameNo, obj.TargetNo, distance.ToString("0.00"))); } else { obj.PSFFit = null; obj.ThisFrameX = (float)expectedX; obj.ThisFrameY = (float)expectedY; obj.ThisFrameCertainty = 0; obj.SetIsLocated(false, NotMeasuredReasons.FailedToLocateAfterDistanceCheck); Trace.WriteLine(string.Format("Frame {0}: Cannot locate object #{1}. A close look up found it {2}px from the expected position.", m_FrameNo, obj.TargetNo, distance.ToString("0.00"))); } } } } else { // Some objects are okay and some are not okay. List<int> badObjectIds = suspectObjects.FindAll(o => goodObjects.IndexOf(o) == -1).Distinct().ToList(); List<int> goodObjectIds = goodObjects.Distinct().ToList(); foreach(int badObjectId in badObjectIds) { double expectedX = 0; double expectedY = 0; TrackedObject badObject = TrackedObjectsByTargetId[badObjectId]; foreach (int goodObjectId in goodObjectIds) { TrackedObject goodObject = TrackedObjectsByTargetId[goodObjectId]; LocationVector vec = goodObject.OtherGuidingStarsLocationVectors[badObjectId]; expectedX += (goodObject.ThisFrameX + vec.DeltaXToAdd); expectedY += (goodObject.ThisFrameY + vec.DeltaYToAdd); } expectedX /= goodObjectIds.Count; expectedY /= goodObjectIds.Count; uint[,] pixels = astroImage.GetPixelsArea((int)Math.Round(expectedX), (int)Math.Round(expectedY), 19); pixels = EnhanceByteAreaForSearch(pixels); PSFFit gaussian = new PSFFit((int)Math.Round(expectedX), (int)Math.Round(expectedY)); gaussian.Fit(pixels, badObject.PsfFitMatrixSize); if (gaussian.IsSolved) { double distance = ImagePixel.ComputeDistance(gaussian.XCenter, expectedX, gaussian.YCenter, expectedY); if (distance <= 2 * PositionTolerance) { // Object successfully located badObject.PSFFit = gaussian; badObject.ThisFrameX = (float)gaussian.XCenter; badObject.ThisFrameY = (float)gaussian.YCenter; badObject.ThisFrameCertainty = (float)gaussian.Certainty; badObject.SetIsLocated(true, NotMeasuredReasons.TrackedSuccessfullyAfterDistanceCheck); Trace.WriteLine(string.Format("Frame {0}: Successfully located object #{1} after a close look up {2}px from the expected position.", m_FrameNo, badObjectId, distance.ToString("0.00"))); } else { badObject.PSFFit = null; badObject.ThisFrameX = (float)expectedX; badObject.ThisFrameY = (float)expectedY; badObject.ThisFrameCertainty = 0; badObject.SetIsLocated(false, NotMeasuredReasons.FailedToLocateAfterDistanceCheck); Trace.WriteLine(string.Format("Frame {0}: Cannot locate object #{1}. A close look up found it {2}px from the expected position.", m_FrameNo, badObjectId, distance.ToString("0.00"))); } } } } } } else if ( goodObjects.Count == 0 && LocateFirstObjects.Count == 1 && float.IsNaN(LocateFirstObjects[0].ThisFrameX)) { // Single 'lost' guiding star or single object (occulted star only) TrackedObject obj1 = LocateFirstObjects[0]; float bestFluctDiff = float.MaxValue; int coeff = LightCurveReductionContext.Instance.WindOrShaking ? 3 : 1; for (int i = 0; i < coeff * obj1.PsfFitMatrixSize; i++) { int searchRadius = obj1.PsfFitMatrixSize + i; IImagePixel centroid = astroImage.GetCentroid( (int) Math.Round(obj1.LastFrameX), (int) Math.Round(obj1.LastFrameY), searchRadius, m_MedianValue); if (centroid != null) { uint[,] pixels = astroImage.GetPixelsArea(centroid.X, centroid.Y, 19); PSFFit gaussian = new PSFFit(centroid.X, centroid.Y); gaussian.Fit(pixels, obj1.PsfFitMatrixSize); if (gaussian.IsSolved) { double brightnessFluctoation = (obj1.RefinedOrLastSignalLevel - gaussian.IMax + gaussian.I0) / obj1.RefinedOrLastSignalLevel; double fluckDiff = Math.Abs(brightnessFluctoation) / m_AllowedSignalFluctoation; if (fluckDiff < 1 || LightCurveReductionContext.Instance.HighFlickeringOrLargeStars) { obj1.PSFFit = gaussian; obj1.ThisFrameX = (float) gaussian.XCenter; obj1.ThisFrameY = (float) gaussian.YCenter; obj1.ThisSignalLevel = (float) (gaussian.IMax - gaussian.I0); obj1.ThisFrameCertainty = (float)gaussian.Certainty; obj1.SetIsLocated(true, NotMeasuredReasons.TrackedSuccessfullyAfterWiderAreaSearch); Trace.WriteLine( string.Format( "Frame {0}: Successfully located object #{1} after a wider search in {2}px region.", m_FrameNo, obj1.TargetNo, searchRadius)); break; } else { if (bestFluctDiff > fluckDiff) bestFluctDiff = (float)fluckDiff; } } } } if (!obj1.IsLocated) { obj1.PSFFit = null; obj1.ThisFrameX = obj1.LastFrameX; obj1.ThisFrameY = obj1.LastFrameY; obj1.ThisSignalLevel = obj1.LastSignalLevel; obj1.ThisFrameCertainty = (float) obj1.LastKnownGoodPsfCertainty; obj1.SetIsLocated(false, NotMeasuredReasons.TrackedSuccessfullyAfterWiderAreaSearch); Trace.WriteLine(string.Format("Frame {0}: Cannot locate object #{1} after a wider search in {2}px region. Best fluct diff: {3}", m_FrameNo, obj1.TargetNo, obj1.PsfFitMatrixSize * 2, bestFluctDiff.ToString("0.00"))); } } }
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; }
private void LocateObjectAsGuidingStar(IAstroImage astroImage, TrackedObject trackedObject, bool useLowPassFilter) { trackedObject.SetIsLocated(false, NotMeasuredReasons.UnknownReason); int bestMaxFixAreaSize = !float.IsNaN(trackedObject.OriginalObject.RefinedFWHM) ? (int)(6 * trackedObject.OriginalObject.RefinedFWHM) : 17; if (bestMaxFixAreaSize > 17) bestMaxFixAreaSize = 35; // We only support FSP Fitting of 17 or 35 square matrixes if (bestMaxFixAreaSize < 17) bestMaxFixAreaSize = 17; // Try all fits from 5 to 15. Find the one with the highest peak, then do a fit around this area with the configured psf matrix size uint[,] pixels; if (useLowPassFilter) { pixels = astroImage.GetPixelsArea((int)trackedObject.LastFrameX, (int)trackedObject.LastFrameY, bestMaxFixAreaSize + 2); pixels = EnhanceByteAreaForSearch(pixels); } else { pixels = astroImage.GetPixelsArea((int)trackedObject.LastFrameX, (int)trackedObject.LastFrameY, bestMaxFixAreaSize); } // There is only one object in the area, just do a wide fit followed by a fit with the selected matrix size PSFFit gaussian = new PSFFit((int)trackedObject.LastFrameX, (int)trackedObject.LastFrameY); gaussian.Fit(pixels, bestMaxFixAreaSize); if (gaussian.Certainty < TangraConfig.Settings.Special.MinGuidingStarCertainty && (trackedObject.LastKnownGoodPsfCertainty > TangraConfig.Settings.Special.GoodGuidingStarCertainty || LightCurveReductionContext.Instance.HighFlickeringOrLargeStars)) { // We have a problem. Try to find the star in the area using other means IImagePixel centroid = astroImage.GetCentroid((int)trackedObject.LastFrameX, (int)trackedObject.LastFrameY, bestMaxFixAreaSize, m_MedianValue); if (centroid != null) { double maxAllowedDistance = !float.IsNaN(trackedObject.OriginalObject.RefinedFWHM) ? 2 * trackedObject.OriginalObject.RefinedFWHM : 3 * TangraConfig.Settings.Special.LostTrackingMinDistance; if (LightCurveReductionContext.Instance.WindOrShaking) maxAllowedDistance *= 1.5; if (centroid.DistanceTo(new ImagePixel((int)trackedObject.LastFrameX, (int)trackedObject.LastFrameY)) < maxAllowedDistance) { pixels = astroImage.GetPixelsArea(centroid.X, centroid.Y, bestMaxFixAreaSize); gaussian = new PSFFit(centroid.X, centroid.Y); gaussian.Fit(pixels, bestMaxFixAreaSize); } } } IImagePixel firstCenter = gaussian.IsSolved ? new ImagePixel(gaussian.Brightness, (int)gaussian.XCenter, (int)gaussian.YCenter) : astroImage.GetCentroid((int)trackedObject.LastFrameX, (int)trackedObject.LastFrameY, bestMaxFixAreaSize, m_MedianValue); if (!gaussian.IsSolved || gaussian.Certainty < TangraConfig.Settings.Special.MinGuidingStarCertainty) firstCenter = null; if (firstCenter != null) { // Do a second fit pixels = astroImage.GetPixelsArea(firstCenter.X, firstCenter.Y, bestMaxFixAreaSize); int secondFitAreaSize = Math.Max(trackedObject.PsfFitMatrixSize, (int)Math.Round(gaussian.FWHM * 2.5)); if (secondFitAreaSize % 2 == 0) secondFitAreaSize++; secondFitAreaSize = Math.Min(17, secondFitAreaSize); gaussian = new PSFFit(firstCenter.X, firstCenter.Y); gaussian.Fit(pixels, secondFitAreaSize); if (gaussian.IsSolved) { double signal = gaussian.IMax - gaussian.I0; if (signal < 0) signal = 0; double brightnessFluctoation = signal > trackedObject.RefinedOrLastSignalLevel ? signal / trackedObject.RefinedOrLastSignalLevel : trackedObject.RefinedOrLastSignalLevel / signal; //double brightnessFluctoation = (trackedObject.RefinedOrLastSignalLevel - gaussian.IMax + gaussian.I0) / trackedObject.RefinedOrLastSignalLevel; double fluckDiff = Math.Abs(brightnessFluctoation)/m_AllowedSignalFluctoation; //if (trackedObject.LastSignalLevel != 0 && // fluckDiff > 1 && // LightCurveReductionContext.Instance.WindOrShaking) //{ // // If the located object is not similar brightness as expected, then search for our object in a wider area // try // { // IImagePixel centroid = astroImage.GetCentroid((int)trackedObject.LastFrameX, (int)trackedObject.LastFrameY, 14, m_MedianValueStart); // pixels = astroImage.GetPixelsArea(centroid.X, centroid.Y, 17); // gaussian = new PSFFit(centroid.X, centroid.Y); // gaussian.Fit(pixels, trackedObject.PsfFitMatrixSize); // if (gaussian.IsSolved) // { // signal = gaussian.IMax - gaussian.I0; if (signal < 0) signal = 0; // brightnessFluctoation = signal > trackedObject.RefinedOrLastSignalLevel // ? signal / trackedObject.RefinedOrLastSignalLevel // : trackedObject.RefinedOrLastSignalLevel / signal; // //brightnessFluctoation = (trackedObject.RefinedOrLastSignalLevel - gaussian.IMax + gaussian.I0) / trackedObject.RefinedOrLastSignalLevel; // fluckDiff = Math.Abs(brightnessFluctoation) / m_AllowedSignalFluctoation; // } // else // { // Trace.WriteLine(string.Format("Frame {0}: Cannot confirm target {1} [Guiding.WindOrShaking]. Cannot solve third PSF", m_FrameNo, trackedObject.TargetNo)); // } // } // catch { } //} if (!trackedObject.HasRefinedPositions || fluckDiff < 1 || LightCurveReductionContext.Instance.HighFlickeringOrLargeStars) { trackedObject.PSFFit = gaussian; trackedObject.ThisFrameX = (float)gaussian.XCenter; trackedObject.ThisFrameY = (float)gaussian.YCenter; trackedObject.ThisSignalLevel = (float)(gaussian.IMax - gaussian.I0); trackedObject.ThisFrameCertainty = (float) gaussian.Certainty; trackedObject.SetIsLocated(true, NotMeasuredReasons.TrackedSuccessfully); if (m_Refining) { trackedObject.RegisterRefinedPosition(trackedObject.Center, trackedObject.ThisSignalLevel, gaussian.FWHM); } } else { if (useLowPassFilter) { // Only show the warning the second time around Trace.WriteLine( string.Format( "Frame {0}: Guiding target #{1} is suspect because the brightness fluctuation is too big: {2}", m_FrameNo, trackedObject.TargetNo, fluckDiff.ToString("0.00"))); trackedObject.SetIsLocated(false, NotMeasuredReasons.GuidingStarBrightnessFluctoationTooHigh); } } } else { Trace.WriteLine(string.Format("Frame {0}: Cannot confirm target {1} [Guiding]. Cannot solve second PSF", m_FrameNo, trackedObject.TargetNo)); trackedObject.SetIsLocated(false, NotMeasuredReasons.PSFFittingFailed); } } else { Trace.WriteLine(string.Format("Frame {0}: Cannot confirm target {1} [Guiding]. Cannot solve first PSF", m_FrameNo, trackedObject.TargetNo)); trackedObject.SetIsLocated(false, NotMeasuredReasons.PSFFittingFailed); } if (!trackedObject.IsLocated) { // Could not locate the object this time trackedObject.ThisSignalLevel = trackedObject.LastSignalLevel; if (m_Refining) { // Use the last known coordinates for refining frames trackedObject.ThisFrameX = trackedObject.LastFrameX; trackedObject.ThisFrameY = trackedObject.LastFrameY; trackedObject.ThisSignalLevel = trackedObject.LastSignalLevel; trackedObject.ThisFrameCertainty = (float)trackedObject.LastKnownGoodPsfCertainty; trackedObject.RegisterRefinedPosition(ImagePixel.Unspecified, float.NaN, double.NaN); } else { // Make the position invalid, which will cause the distance check for this object to fail // which will trigger another fitting later on. Eventually the previous position may be still used trackedObject.ThisFrameX = float.NaN; trackedObject.ThisFrameY = float.NaN; trackedObject.ThisFrameCertainty = float.NaN; } } }
internal frmAddOrEditSingleTarget(int objectId, ImagePixel center, PSFFit gaussian, LCStateMachine state, VideoController videoController) { InitializeComponent(); m_VideoController = videoController; m_AutocenteredApertureAvailable = true; Text = "Add Object"; btnAdd.Text = "Add"; btnDontAdd.Text = "Don't Add"; btnDelete.Visible = false; m_IsEdit = false; nudFitMatrixSize.Value = 11; nudFitMatrixSize.Maximum = 15; m_ObjectId = objectId; m_State = state; m_AstroImage = m_State.VideoOperation.m_StackedAstroImage; ObjectToAdd = new TrackedObjectConfig(); m_Center = new ImagePixel(center); Initialize(); if (rbOccultedStar.Enabled) SelectedObjectType = TrackingType.OccultedStar; else SelectedObjectType = TrackingType.GuidingStar; // Apply filtering to the processing pixels according to the configured default filter value int matirxSize = (int)nudFitMatrixSize.Value; GetFitInMatrix(gaussian, ref matirxSize); nudFitMatrixSize.Maximum = matirxSize; if (SelectedObjectType != TrackingType.OccultedStar) SetHeightAndType(); }
public static PSFFit GetPSFFitForPeakPixel( uint[,] data, PotentialStarStruct starToTest, float aboveNoiseLevelRequired, double minFWHM, double maxFWHM) { int STAR_MATRIX_FIT = TangraConfig.Settings.Special.StarFinderFitArea; double MIN_DISTANCE_OF_PEAK_PIXEL_FROM_CENTER = TangraConfig.Settings.Special.StarFinderMinDistanceOfPeakPixelFromCenter; PSFFit fit = new PSFFit(starToTest.X, starToTest.Y); int fitMatrix = (int)Math.Min(data.GetLength(0), STAR_MATRIX_FIT + 2); // Get a matrix with 1 pixel larger each way and set the border pixels to zero fit.Fit(data, fitMatrix, starToTest.X, starToTest.Y, true); if (fit.IsSolved) { double distanceFromCenter = ImagePixel.ComputeDistance(fit.X0_Matrix, fitMatrix / 2, fit.Y0_Matrix, fitMatrix / 2); if (fit.Certainty > 0 && fit.FWHM >= minFWHM && fit.FWHM <= maxFWHM && distanceFromCenter < MIN_DISTANCE_OF_PEAK_PIXEL_FROM_CENTER && fit.IMax > aboveNoiseLevelRequired) { //not good for lost tracking allow higher FWHM // This object passes all tests to be furhter considered as a star return fit; } } return null; }
private bool GetFitInMatrix(ITrackedObjectPsfFit gaussian, ref int matirxSize, float preselectedAperture) { rbGuidingStar.Text = "Guiding 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 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 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; } }
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); }
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; }
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 picTarget1Pixels_Click(object sender, EventArgs e) { if (newStar != null) { m_Gaussian = newStar; m_X0 = (float)newStar.XCenter; m_Y0 = (float)newStar.YCenter; m_FWHM = (float)newStar.FWHM; nudFitMatrixSize.ValueChanged -= nudFitMatrixSize_ValueChanged; try { nudFitMatrixSize.SetNUDValue(newStar.MatrixSize); } finally { nudFitMatrixSize.ValueChanged += nudFitMatrixSize_ValueChanged; } PlotSingleTargetPixels(); PlotGaussian(); } }
protected virtual void TrackSingleStar(int frameNo, IAstroImage astroImage) { OccultedStar.NewFrame(); m_NotCertain = false; float expectedX; float expectedY; GetExpectedXY(out expectedX, out expectedY); uint[,] pixels = astroImage.GetPixelsArea((int)expectedX, (int)expectedY, 17); // There is only one object in the area, just do a wide fit followed by a fit with the selected matrix size PSFFit gaussian = new PSFFit((int)expectedX, (int)expectedY); gaussian.Fit(pixels, 17); IImagePixel firstCenter = gaussian.IsSolved ? new ImagePixel((int)gaussian.XCenter, (int)gaussian.YCenter) : astroImage.GetCentroid((int)expectedX, (int)expectedY, 17, m_MedianValue); if (firstCenter != null) { // Do a second fit pixels = astroImage.GetPixelsArea(firstCenter.X, firstCenter.Y, 17); gaussian = new PSFFit(firstCenter.X, firstCenter.Y); gaussian.Fit(pixels, OccultedStar.PsfFitMatrixSize); if (gaussian.IsSolved) { double signal = gaussian.IMax - gaussian.I0; if (signal < 0) signal = 0; double brightnessFluctoation = signal > OccultedStar.RefinedOrLastSignalLevel ? signal / OccultedStar.RefinedOrLastSignalLevel : OccultedStar.RefinedOrLastSignalLevel / signal; //double brightnessFluctoation = (trackedObject.RefinedOrLastSignalLevel - gaussian.IMax + gaussian.I0) / trackedObject.RefinedOrLastSignalLevel; double fluckDiff = Math.Abs(brightnessFluctoation) / m_AllowedSignalFluctoation; if (fluckDiff < 1 || LightCurveReductionContext.Instance.HighFlickeringOrLargeStars) { OccultedStar.PSFFit = gaussian; OccultedStar.ThisFrameX = (float)gaussian.XCenter; OccultedStar.ThisFrameY = (float)gaussian.YCenter; OccultedStar.ThisSignalLevel = (float)(gaussian.IMax - gaussian.I0); OccultedStar.ThisFrameCertainty = (float)gaussian.Certainty; OccultedStar.SetIsLocated(true, NotMeasuredReasons.TrackedSuccessfully); } else { m_NotCertain = true; // This is the Occulted Star, so no brightness fluctoations can be used as excuses! FitObjectInLimitedArea(OccultedStar, astroImage, expectedX, expectedY); OccultedStar.SetIsLocated( LightCurveReductionContext.Instance.FullDisappearance || OccultedStar.PSFFit != null, LightCurveReductionContext.Instance.FullDisappearance || OccultedStar.PSFFit != null ? NotMeasuredReasons.TrackedSuccessfully : NotMeasuredReasons.DistanceToleranceTooHighForNonFullDisappearingOccultedStar); m_NotCertain = !OccultedStar.IsLocated; } } else { OccultedStar.ThisFrameX = expectedX; OccultedStar.ThisFrameY = expectedY; OccultedStar.ThisFrameCertainty = (float)gaussian.Certainty; Trace.WriteLine(string.Format("Frame {0}: Cannot confirm target {1} [SingleStar]. Cannot solve second PSF", m_FrameNo, OccultedStar.TargetNo)); OccultedStar.SetIsLocated(false, NotMeasuredReasons.PSFFittingFailed); } } else { OccultedStar.ThisFrameX = expectedX; OccultedStar.ThisFrameY = expectedY; OccultedStar.ThisFrameCertainty = (float)gaussian.Certainty; Trace.WriteLine(string.Format("Frame {0}: Cannot confirm target {1} [SingleStar]. Cannot solve first PSF", m_FrameNo, OccultedStar.TargetNo)); OccultedStar.SetIsLocated(false, NotMeasuredReasons.PSFFittingFailed); } }
private void picTarget1Pixels_MouseMove(object sender, MouseEventArgs e) { if (m_AutoStarsInArea != null && m_AutoStarsInArea.Count > 1) { float x = e.X / 7.0f; float y = e.Y / 7.0f; PSFFit star = m_AutoStarsInArea.Find( s => { return Math.Abs(s.XCenter - x + 0.5f) < 2.0f && Math.Abs(s.YCenter - y + 0.5) < 2.0f; } ); if (star != null && m_Gaussian.UniqueId != star.UniqueId) { newStar = star; Cursor = Cursors.Hand; } else Cursor = Cursors.Default; } }
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); } } }
protected void FitObjectInLimitedArea(TrackedObject trackedObject, IAstroImage astroImage, float startingX, float startingY) { int smallestMatrixSize = (int)Math.Round(trackedObject.OriginalObject.ApertureInPixels * 2); if (smallestMatrixSize % 2 == 0) smallestMatrixSize++; // If this is not an aperture photometry we still derive a PSF uint[,] pixels = astroImage.GetPixelsArea((int)Math.Round(startingX), (int)Math.Round(startingY), 17); bool isFSPSolved = false; bool isTooFar = true; for (int i = Math.Max(trackedObject.PsfFitMatrixSize, smallestMatrixSize); i >= smallestMatrixSize; i -= 2) { int borderZeroes = (trackedObject.PsfFitMatrixSize - i) / 2; for (int x = 0; x < pixels.GetLength(0); x++) { for (int y = 0; y < borderZeroes; y++) { pixels[x, y] = 0; pixels[x, pixels.GetLength(1) - y - 1] = 0; } } for (int y = 0; y < pixels.GetLength(1); y++) { for (int x = 0; x < borderZeroes; x++) { pixels[x, y] = 0; pixels[pixels.GetLength(0) - x - 1, y] = 0; } } PSFFit gaussian = new PSFFit((int)Math.Round(startingX), (int)Math.Round(startingY)); gaussian.Fit(pixels, trackedObject.PsfFitMatrixSize); isFSPSolved = gaussian.IsSolved; isTooFar = true; if (gaussian.IsSolved) { trackedObject.ThisFrameCertainty = (float)gaussian.Certainty; double dist = ImagePixel.ComputeDistance((float)gaussian.XCenter, (float)startingX, (float)gaussian.YCenter, (float)startingY); if (dist <= PositionTolerance) { isTooFar = false; trackedObject.PSFFit = gaussian; trackedObject.ThisFrameX = (float)gaussian.XCenter; trackedObject.ThisFrameY = (float)gaussian.YCenter; trackedObject.ThisSignalLevel = (float)(gaussian.IMax - gaussian.I0); trackedObject.ThisFrameCertainty = (float)gaussian.Certainty; trackedObject.SetIsLocated(true, NotMeasuredReasons.TrackedSuccessfully); return; } } } trackedObject.PSFFit = null; trackedObject.ThisFrameX = startingX; trackedObject.ThisFrameY = startingY; trackedObject.SetIsLocated(false, !isFSPSolved ? NotMeasuredReasons.PSFFittingFailed : isTooFar ? NotMeasuredReasons.FoundObjectNotWithInExpectedPositionTolerance : NotMeasuredReasons.UnknownReason); }