public SafeMatrix Minor(int row, int col) { // THIS IS THE LOW-LEVEL SOLUTION ~ O(n^2) SafeMatrix buf = new SafeMatrix(m_RowCount - 1, m_ColumnCount - 1); int r = 0; int c = 0; for (int i = 0; i < m_RowCount; i++) { if (i != row) { for (int j = 0; j < m_ColumnCount; j++) { if (j != col) { buf.m_Elements[r * buf.m_ColumnCount + c] = m_Elements[i * m_ColumnCount + j]; c++; } } c = 0; r++; } } return(buf); }
/// <summary> /// Inverts square matrix as long as det != 0. /// </summary> /// <returns>Inverse of matrix.</returns> public SafeMatrix Inverse() { if (!this.IsSquare()) { throw new InvalidOperationException("Cannot invert non-square matrix."); } double det = this.Determinant(); if (det == 0) { throw new InvalidOperationException("Cannot invert (nearly) singular matrix."); } SafeMatrix buf = new SafeMatrix(m_ColumnCount, m_ColumnCount); for (int i = 0; i < m_ColumnCount; i++) { for (int j = 0; j < m_ColumnCount; j++) { buf.m_Elements[i * buf.m_ColumnCount + j] = (Math.Pow(-1, i + j) * this.Minor(j, i).Determinant()) / det; } } return(buf); }
public void SolveNoWeights() { if (m_XValues.Count < 3) { throw new InvalidOperationException("Cannot get a linear fit from less than 3 points."); } SafeMatrix A = new SafeMatrix(m_XValues.Count, 2); SafeMatrix X = new SafeMatrix(m_XValues.Count, 1); for (int i = 0; i < m_XValues.Count; i++) { A[i, 0] = m_XValues[i]; A[i, 1] = 1; X[i, 0] = m_YValues[i]; } SafeMatrix a_T = A.Transpose(); SafeMatrix aa = a_T * A; SafeMatrix aa_inv = m_CoVarianceMatrix = aa.Inverse(); SafeMatrix bx = (aa_inv * a_T) * X; m_A = bx[0, 0]; m_B = bx[1, 0]; }
public double Determinant() { if (!this.IsSquare()) { throw new InvalidOperationException("Cannot calc determinant of non-square matrix."); } if (this.m_ColumnCount == 1) { return(this[0, 0]); } // perform LU-decomposition & return product of diagonal elements of U SafeMatrix X = this.Clone(); // for speed concerns, use this try { X.LU(); return(X.DiagProd()); } catch (DivideByZeroException) { // this is slower and needs more memory... . //Matrix P = X.LUSafe(); //return (double)P.Signum() * X.DiagProd(); throw; } }
public static SafeMatrix operator *(double x, SafeMatrix A) { SafeMatrix B = new SafeMatrix(A.RowCount, A.ColumnCount); for (int i = 0; i < A.m_MatrixSize; i++) { B.m_Elements[i] = A.m_Elements[i] * x; } return(B); }
public SafeMatrix Clone() { SafeMatrix A = new SafeMatrix(m_RowCount, m_ColumnCount); for (int i = 0; i < m_MatrixSize; i++) { A.m_Elements[i] = m_Elements[i]; } return(A); }
public static SafeMatrix SolveLinearSystem(SafeMatrix A, SafeMatrix X) { double[] a = A.GetElements(); double[] x = X.GetElements(); double[] y = new double[A.ColumnCount * X.ColumnCount]; SolveLinearSystem(a, A.RowCount, A.ColumnCount, x, X.RowCount, X.ColumnCount, y); SafeMatrix rv = new SafeMatrix(X.RowCount, X.ColumnCount); rv.SetElements(y); return rv; }
public SafeMatrix Transpose() { SafeMatrix M = new SafeMatrix(m_ColumnCount, m_RowCount); for (int i = 0; i < m_ColumnCount; i++) { for (int j = 0; j < m_RowCount; j++) { M.m_Elements[i * M.m_ColumnCount + j] = m_Elements[j * m_ColumnCount + i]; } } return(M); }
public static double Dot(SafeMatrix v, int vRow, SafeMatrix w, int wCol) { if (v.ColumnCount != w.RowCount) { throw new ArgumentException("Vectors must be of the same length."); } double buf = 0; for (int i = 0; i < v.ColumnCount; i++) { buf += v.m_Elements[vRow * v.m_ColumnCount + i] * w.m_Elements[i * w.m_ColumnCount + wCol]; } return(buf); }
public static SafeMatrix operator *(SafeMatrix A, SafeMatrix B) { if (A.ColumnCount != B.RowCount) { throw new ArgumentException("Inner matrix dimensions must agree."); } SafeMatrix C = new SafeMatrix(A.RowCount, B.ColumnCount); for (int i = 0; i < A.RowCount; i++) { for (int j = 0; j < B.ColumnCount; j++) { C.m_Elements[i * C.m_ColumnCount + j] = Dot(A, i, B, j); } } return(C); }
/// <summary> /// Warning: This method is not thread safe! /// </summary> public static SafeMatrix SolveLinearSystemFast(SafeMatrix A, SafeMatrix X) { if (A.RowCount > 35 * 35) throw new InvalidOperationException("Not a PSF fitting linear system."); if (s_NumVariables != A.ColumnCount) { LinearSystemFastInitialiseSolution(A.ColumnCount, 35*35); s_NumVariables = A.ColumnCount; } double[] a = A.GetElements(); double[] x = X.GetElements(); double[] y = new double[A.ColumnCount * X.ColumnCount]; SolveLinearSystemFast(a, x, A.RowCount, y); SafeMatrix rv = new SafeMatrix(X.RowCount, X.ColumnCount); rv.SetElements(y); return rv; }
// I(x, y) = IBackground + IStarMax * Exp ( -((x - X0)*(x - X0) + (y - Y0)*(y - Y0)) / (r0 * r0)) private void NonLinearFit(uint[,] intensity, bool useNativeMatrix) { m_IsSolved = false; try { int full_width = (int) Math.Round(Math.Sqrt(intensity.Length)); m_MatrixSize = full_width; int half_width = full_width/2; m_HalfWidth = half_width; switch (DataRange) { case PSFFittingDataRange.DataRange8Bit: m_Saturation = TangraConfig.Settings.Photometry.Saturation.Saturation8Bit; break; case PSFFittingDataRange.DataRange12Bit: m_Saturation = TangraConfig.Settings.Photometry.Saturation.Saturation12Bit; break; case PSFFittingDataRange.DataRange14Bit: m_Saturation = TangraConfig.Settings.Photometry.Saturation.Saturation14Bit; break; case PSFFittingDataRange.DataRange16Bit: m_Saturation = NormVal > 0 ? (uint)(TangraConfig.Settings.Photometry.Saturation.Saturation8Bit * NormVal / 255.0) : TangraConfig.Settings.Photometry.Saturation.Saturation16Bit; break; default: m_Saturation = TangraConfig.Settings.Photometry.Saturation.Saturation8Bit; break; } int nonSaturatedPixels = 0; double IBackground = 0; double r0 = 4.0; double IStarMax = 0; double found_x = half_width; double found_y = half_width; for (int iter = NumberIterations; iter > 0; iter--) { if (iter == NumberIterations) { uint zval = 0; IBackground = 0.0; /* assume no backgnd intensity at first... */ for (int i = 0; i < full_width; i++) { for (int j = 0; j < full_width; j++) { if (intensity[i, j] > zval) zval = intensity[i, j]; if (intensity[i, j] < m_Saturation) nonSaturatedPixels++; } } IStarMax = (double) zval - IBackground; } double[] dx = new double[full_width]; double[] dy = new double[full_width]; double[] fx = new double[full_width]; double[] fy = new double[full_width]; double r0_squared = r0*r0; for (int i = 0; i < full_width; i++) { dx[i] = (double) i - found_x; fx[i] = Math.Exp(-dx[i]*dx[i]/r0_squared); dy[i] = (double) i - found_y; fy[i] = Math.Exp(-dy[i]*dy[i]/r0_squared); } SafeMatrix A = new SafeMatrix(nonSaturatedPixels, 5); SafeMatrix X = new SafeMatrix(nonSaturatedPixels, 1); int index = -1; for (int i = 0; i < full_width; i++) { for (int j = 0; j < full_width; j++) { double zval = intensity[i, j]; if (zval < m_Saturation) { index++; if (m_BackgroundModel != null) zval -= m_BackgroundModel.ComputeValue(i + m_BackgroundModelOffset, j + m_BackgroundModelOffset); double exp_val = fx[i]*fy[j]; double residual = IBackground + IStarMax*exp_val - zval; X[index, 0] = -residual; A[index, 0] = 1.0; /* slope in i0 */ A[index, 1] = exp_val; /* slope in a0 */ A[index, 2] = 2.0*IStarMax*dx[i]*exp_val/r0_squared; A[index, 3] = 2.0*IStarMax*dy[j]*exp_val/r0_squared; A[index, 4] = 2.0*IStarMax*(dx[i]*dx[i] + dy[j]*dy[j])*exp_val/(r0*r0_squared); } } } SafeMatrix Y; if (useNativeMatrix) { Y = TangraModelCore.SolveLinearSystemFast(A, X); } else { SafeMatrix a_T = A.Transpose(); SafeMatrix aa = a_T * A; SafeMatrix aa_inv = aa.Inverse(); Y = (aa_inv * a_T) * X; } /* we need at least 6 unsaturated pixels to solve 5 params */ if (nonSaturatedPixels > 6) /* Request all pixels to be good! */ { IBackground += Y[0, 0]; IStarMax += Y[1, 0]; for (int i = 2; i < 4; i++) { if (Y[i, 0] > 1.0) Y[i, 0] = 1.0; if (Y[i, 0] < -1.0) Y[i, 0] = -1.0; } found_x += Y[2, 0]; found_y += Y[3, 0]; if (Y[4, 0] > r0/10.0) Y[4, 0] = r0/10.0; if (Y[4, 0] < -r0/10.0) Y[4, 0] = -r0/10.0; r0 += Y[4, 0]; } else { m_IsSolved = false; return; } } m_IsSolved = true; m_IBackground = IBackground; m_IStarMax = IStarMax; m_X0 = found_x; m_Y0 = found_y; m_R0 = r0; m_SNR = null; m_Residuals = new double[full_width,full_width]; for (int x = 0; x < full_width; x++) for (int y = 0; y < full_width; y++) { m_Residuals[x, y] = intensity[x, y] - GetPSFValueInternal(x, y); } } catch(DivideByZeroException) { } }
public FocalLengthFit ComputeFocalLengthFit() { if (m_FocalLengthFit != null) return m_FocalLengthFit; List<DistSolveEntry> entries = new List<DistSolveEntry>(); for (int i = 0; i < m_Pairs.Count; i++) { if (!m_Pairs[i].FitInfo.UsedInSolution) continue; if (m_Pairs[i].FitInfo.ExcludedForHighResidual) continue; for (int j = 0; j < m_Pairs.Count; j++) { if (i == j) continue; if (!m_Pairs[j].FitInfo.UsedInSolution) continue; if (m_Pairs[j].FitInfo.ExcludedForHighResidual) continue; DistSolveEntry entry = new DistSolveEntry(); entry.DX = Math.Abs(m_Pairs[i].x - m_Pairs[j].x); entry.DY = Math.Abs(m_Pairs[i].y - m_Pairs[j].y); entry.StarNo1 = m_Pairs[i].StarNo; entry.StarNo2 = m_Pairs[j].StarNo; // NOTE: two ways of computing distances - by vx,vy,vz and Elongation() //entry.DistRadians = Math.Acos(m_Pairs[i].VX * m_Pairs[j].VX + m_Pairs[i].VY * m_Pairs[j].VY + m_Pairs[i].VZ * m_Pairs[j].VZ); double elong = AngleUtility.Elongation(m_Pairs[i].RADeg, m_Pairs[i].DEDeg, m_Pairs[j].RADeg, m_Pairs[j].DEDeg); entry.DistRadians = elong * Math.PI / 180.0; if (entry.DX == 0 || entry.DY == 0) continue; entries.Add(entry); } } SafeMatrix A = new SafeMatrix(entries.Count, 2); SafeMatrix X = new SafeMatrix(entries.Count, 1); int numStars = 0; foreach (DistSolveEntry entry in entries) { A[numStars, 0] = entry.DX * entry.DX; A[numStars, 1] = entry.DY * entry.DY; X[numStars, 0] = entry.DistRadians * entry.DistRadians; numStars++; } // Insufficient stars to solve the plate if (numStars < 3) return null; SafeMatrix a_T = A.Transpose(); SafeMatrix aa = a_T * A; SafeMatrix aa_inv = aa.Inverse(); SafeMatrix bx = (aa_inv * a_T) * X; double a = bx[0, 0]; double b = bx[1, 0]; double residualSum = 0; int numResiduals = 0; foreach (DistSolveEntry entry in entries) { entry.ResidualRadians = entry.DistRadians - Math.Sqrt(a * entry.DX * entry.DX + b * entry.DY * entry.DY); entry.ResidualPercent = entry.ResidualRadians * 100.0 / entry.DistRadians; entry.ResidualArcSec = 3600.0 * entry.ResidualRadians * 180.0 / Math.PI; numResiduals++; residualSum += entry.ResidualRadians * entry.ResidualRadians; } double variance = Math.Sqrt(residualSum / (numResiduals - 1)); return new FocalLengthFit(a, b, variance, entries); }
private void CalibrateNonLinearMagModelInternal(List<AbsFluxSpectra> standards) { m_MagnitudeCoefficients.Clear(); m_ExtinctionCoefficients.Clear(); m_SensitivityCoefficients.Clear(); m_Wavelengths.Clear(); for (int i = 0; i < standards[0].DeltaMagnitiudes.Count; i++) { var A = new SafeMatrix(standards.Count, 3); var X = new SafeMatrix(standards.Count, 1); bool containsNaNs = false; // MagAbs = A * MagInst + B * X + C = Km * MagInst + Ke * X + Ks for (int j = 0; j < standards.Count; j++) { A[j, 0] = -2.5 * Math.Log10(standards[j].ObservedFluxes[i] / standards[j].InputFile.Exposure); A[j, 1] = standards[j].InputFile.AirMass; A[j, 2] = 1; double absMag = -2.5 * Math.Log10(standards[j].AbsoluteFluxes[i]); X[j, 0] = absMag; if (double.IsNaN(absMag) || double.IsNaN(A[j, 0])) containsNaNs = true; } m_Wavelengths.Add(standards[0].ResolvedWavelengths[i]); if (!containsNaNs) { SafeMatrix a_T = A.Transpose(); SafeMatrix aa = a_T * A; SafeMatrix aa_inv = aa.Inverse(); SafeMatrix bx = (aa_inv * a_T) * X; float km = (float)bx[0, 0]; float ke = (float)bx[1, 0]; float ks = (float)bx[2, 0]; m_MagnitudeCoefficients.Add(km); m_ExtinctionCoefficients.Add(ke); m_SensitivityCoefficients.Add(ks); } else { m_MagnitudeCoefficients.Add(double.NaN); m_ExtinctionCoefficients.Add(double.NaN); m_SensitivityCoefficients.Add(double.NaN); } } }
private void CalibrateLinearModelInternal(List<AbsFluxSpectra> standards) { m_MagnitudeCoefficients.Clear(); m_ExtinctionCoefficients.Clear(); m_SensitivityCoefficients.Clear(); m_Wavelengths.Clear(); for (int i = 0; i < standards[0].DeltaMagnitiudes.Count; i++) { var A = new SafeMatrix(standards.Count, 2); var X = new SafeMatrix(standards.Count, 1); bool containsNaNs = false; // Delta_Mag = A * X + B = Ke * X + Ks for (int j = 0; j < standards.Count; j++) { A[j, 0] = standards[j].InputFile.AirMass; A[j, 1] = 1; double deltaMag = standards[j].DeltaMagnitiudes[i]; X[j, 0] = deltaMag; if (double.IsNaN(deltaMag)) containsNaNs = true; } m_Wavelengths.Add(standards[0].ResolvedWavelengths[i]); if (!containsNaNs) { SafeMatrix a_T = A.Transpose(); SafeMatrix aa = a_T * A; SafeMatrix aa_inv = aa.Inverse(); SafeMatrix bx = (aa_inv * a_T) * X; float ke = (float)bx[0, 0]; float ks = (float)bx[1, 0]; m_MagnitudeCoefficients.Add(1); m_ExtinctionCoefficients.Add(ke); m_SensitivityCoefficients.Add(ks); } else { m_MagnitudeCoefficients.Add(double.NaN); m_ExtinctionCoefficients.Add(double.NaN); m_SensitivityCoefficients.Add(double.NaN); } } }
protected abstract void ReadSolvedReversedConstants(SafeMatrix bx, SafeMatrix by);
internal void GenerateBackgroundModelParameters(int order, double depth) { Random rnd = new Random((int)DateTime.Now.Ticks); if (order == 1) { // z = ax + by + c int dist = rnd.Next(m_X0, m_X0 + (int)(1.2 * m_Radius)); int d2 = rnd.Next((int)depth / 2, (int)depth); SafeMatrix A = new SafeMatrix(3, 3); SafeMatrix X = new SafeMatrix(3, 1); A[0, 0] = m_X0; A[0, 1] = m_Y0; A[0, 2] = 1; X[0, 0] = depth; A[1, 0] = m_X0 + dist / 2; A[1, 1] = m_Y0 + dist / 3; A[1, 2] = 1; X[1, 0] = d2; A[2, 0] = m_X0 + dist; A[2, 1] = m_Y0 + dist / 2; A[2, 2] = 1; X[2, 0] = 0; SafeMatrix a_T = A.Transpose(); SafeMatrix aa = a_T * A; SafeMatrix aa_inv = aa.Inverse(); SafeMatrix bx = (aa_inv * a_T) * X; this.A = bx[0, 0]; B = bx[1, 0]; C = bx[2, 0]; } else if (order == 2) { // z = axx + bxy + cyy + dx + ey + f int[] xArr = new int[6]; int[] yArr = new int[6]; double[] zArr = new double[6]; xArr[0] = m_X0; yArr[0] = m_Y0; zArr[0] = depth; xArr[1] = m_X0 + m_Radius; yArr[1] = m_Y0 + m_Radius / 3; zArr[1] = 0; for (int i = 2; i < 6; i++) { xArr[i] = rnd.Next(m_X0, m_X0 + (int)(1.2 * m_Radius)); yArr[i] = rnd.Next(m_Y0, m_Y0 + (int)(0.6 * m_Radius)); zArr[i] = rnd.Next(0, (int)depth); } // Start with an approximation // z = axx + + cyy + + f SafeMatrix A = new SafeMatrix(3, 3); SafeMatrix X = new SafeMatrix(3, 1); for (int i = 0; i < 3; i++) { A[i, 0] = xArr[i] * xArr[i]; A[i, 1] = yArr[i] * yArr[i]; A[i, 2] = 1; X[i, 0] = zArr[i]; } SafeMatrix a_T = A.Transpose(); SafeMatrix aa = a_T * A; SafeMatrix aa_inv = aa.Inverse(); SafeMatrix bx = (aa_inv * a_T) * X; this.A = bx[0, 0]; C = bx[1, 0]; F = bx[2, 0]; B = 0; D = 0; E = 0; /* A = new SafeMatrix(6, 6); X = new SafeMatrix(6, 1); for (int i = 0; i < 6; i++) { A[i, 0] = xArr[i] * xArr[i]; A[i, 1] = xArr[i] * yArr[i]; A[i, 2] = yArr[i] * yArr[i]; A[i, 3] = xArr[i]; A[i, 4] = yArr[i]; A[i, 5] = 1; X[i, 0] = zArr[i]; } a_T = A.Transpose(); aa = a_T * A; aa_inv = aa.Inverse(); bx = (aa_inv * a_T) * X; m_A = bx[0, 0]; m_B = bx[1, 0]; m_C = bx[2, 0]; m_D = bx[3, 0]; m_E = bx[4, 0]; m_F = bx[5, 0]; */ } else if (order == 3) { // z = axxx + bxxy + cxyy + dyyy + exx + fxy + gyy + hx + iy + j int[] xArr = new int[10]; int[] yArr = new int[10]; double[] zArr = new double[10]; xArr[0] = m_X0; yArr[0] = m_Y0; zArr[0] = depth; xArr[1] = m_X0 + m_Radius; yArr[1] = m_Y0 + m_Radius / 3; zArr[1] = 0; for (int i = 2; i < 6; i++) { xArr[i] = rnd.Next(m_X0, m_X0 + (int)(1.2 * m_Radius)); yArr[i] = rnd.Next(m_Y0, m_Y0 + (int)(0.6 * m_Radius)); zArr[i] = rnd.Next(0, (int)depth); } // Start with an approximation // z = axxx + + dyyy + + fxy + + j SafeMatrix A = new SafeMatrix(4, 4); SafeMatrix X = new SafeMatrix(4, 1); for (int i = 0; i < 4; i++) { A[i, 0] = xArr[i] * xArr[i] * xArr[i]; A[i, 1] = yArr[i] * yArr[i] * yArr[i]; A[i, 2] = xArr[i] * yArr[i]; A[i, 3] = 1; X[i, 0] = zArr[i]; } SafeMatrix a_T = A.Transpose(); SafeMatrix aa = a_T * A; SafeMatrix aa_inv = aa.Inverse(); SafeMatrix bx = (aa_inv * a_T) * X; this.A = bx[0, 0]; D = bx[1, 0]; F = bx[2, 0]; J = bx[3, 0]; B = 0; C = 0; E = 0; G = 0; H = 0; I = 0; } }
public static StarMagnitudeFit PerformFit( IAstrometryController astrometryController, IVideoController videoController, int bitPix, uint maxSignalValue, FitInfo astrometricFit, TangraConfig.PhotometryReductionMethod photometryReductionMethod, TangraConfig.PsfQuadrature psfQuadrature, TangraConfig.PsfFittingMethod psfFittingMethod, TangraConfig.BackgroundMethod photometryBackgroundMethod, TangraConfig.PreProcessingFilter filter, List<IStar> catalogueStars, Guid magnitudeBandId, float encodingGamma, TangraConfig.KnownCameraResponse reverseCameraResponse, float? aperture, float? annulusInnerRadius, int? annulusMinPixels, ref float empericalPSFR0) { uint saturatedValue = TangraConfig.Settings.Photometry.Saturation.GetSaturationForBpp(bitPix, maxSignalValue); MeasurementsHelper measurer = new MeasurementsHelper( bitPix, photometryBackgroundMethod, TangraConfig.Settings.Photometry.SubPixelSquareSize, saturatedValue); measurer.SetCoreProperties( annulusInnerRadius ?? TangraConfig.Settings.Photometry.AnnulusInnerRadius, annulusMinPixels ?? TangraConfig.Settings.Photometry.AnnulusMinPixels, CorePhotometrySettings.Default.RejectionBackgroundPixelsStdDev, 2 /* TODO: This must be configurable */); var bgProvider = new BackgroundProvider(videoController); measurer.GetImagePixelsCallback += new MeasurementsHelper.GetImagePixelsDelegate(bgProvider.measurer_GetImagePixelsCallback); List<double> intencities = new List<double>(); List<double> magnitudes = new List<double>(); List<double> colours = new List<double>(); List<double> residuals = new List<double>(); List<bool> saturatedFlags = new List<bool>(); List<IStar> stars = new List<IStar>(); List<PSFFit> gaussians = new List<PSFFit>(); List<MagFitRecord> fitRecords = new List<MagFitRecord>(); AstroImage currentAstroImage = videoController.GetCurrentAstroImage(false); Rectangle osdRectToExclude = astrometryController.OSDRectToExclude; Rectangle rectToInclude = astrometryController.RectToInclude; bool limitByInclusion = astrometryController.LimitByInclusion; int matSize = CorePhotometrySettings.Default.MatrixSizeForCalibratedPhotometry; double a = double.NaN; double b = double.NaN; double c = double.NaN; int excludedStars = 0; double empericalFWHM = double.NaN; try { foreach (PlateConstStarPair pair in astrometricFit.AllStarPairs) { if (limitByInclusion && !rectToInclude.Contains((int)pair.x, (int)pair.y)) continue; if (!limitByInclusion && osdRectToExclude.Contains((int)pair.x, (int)pair.y)) continue; IStar star = catalogueStars.Find(s => s.StarNo == pair.StarNo); if (star == null || double.IsNaN(star.Mag) || star.Mag == 0) continue; uint[,] data = currentAstroImage.GetMeasurableAreaPixels((int)pair.x, (int)pair.y, matSize); PSFFit fit = new PSFFit((int)pair.x, (int)pair.y); fit.Fit(data, PSF_FIT_AREA_SIZE); if (!fit.IsSolved) continue; MagFitRecord record = new MagFitRecord(); record.Star = star; record.Pair = pair; record.PsfFit = fit; record.Saturation = IsSaturated(data, matSize, saturatedValue); if (!EXCLUDE_SATURATED_STARS || !record.Saturation) fitRecords.Add(record); } // We need the average R0 if it hasn't been determined yet if (float.IsNaN(empericalPSFR0)) { empericalPSFR0 = 0; foreach (MagFitRecord rec in fitRecords) { empericalPSFR0 += (float)rec.PsfFit.R0; } empericalPSFR0 /= fitRecords.Count; } empericalFWHM = 2 * Math.Sqrt(Math.Log(2)) * empericalPSFR0; foreach (MagFitRecord record in fitRecords) { ImagePixel center = new ImagePixel(255, record.Pair.x, record.Pair.y); int areaSize = filter == TangraConfig.PreProcessingFilter.NoFilter ? 17 : 19; int centerX = (int)Math.Round(center.XDouble); int centerY = (int)Math.Round(center.YDouble); uint[,] data = currentAstroImage.GetMeasurableAreaPixels(centerX, centerY, areaSize); uint[,] backgroundPixels = currentAstroImage.GetMeasurableAreaPixels(centerX, centerY, 35); measurer.MeasureObject( center, data, backgroundPixels, currentAstroImage.Pixelmap.BitPixCamera, filter, photometryReductionMethod, psfQuadrature, psfFittingMethod, aperture != null ? aperture.Value : (float)Aperture(record.PsfFit.FWHM), record.PsfFit.FWHM, (float)empericalFWHM, new FakeIMeasuredObject(record.PsfFit), null, null, false); double intensity = measurer.TotalReading - measurer.TotalBackground; if (intensity > 0) { var mag = record.Star.GetMagnitudeForBand(magnitudeBandId); var clr = record.Star.MagJ - record.Star.MagK; if (!double.IsNaN(mag) && !double.IsNaN(clr) && !double.IsInfinity(mag) && !double.IsInfinity(clr)) { intencities.Add(intensity); magnitudes.Add(record.Star.GetMagnitudeForBand(magnitudeBandId)); colours.Add(record.Star.MagJ - record.Star.MagK); gaussians.Add(record.PsfFit); stars.Add(record.Star); saturatedFlags.Add(measurer.HasSaturatedPixels || record.PsfFit.IMax >= measurer.SaturationValue); } } } // Remove stars with unusual PSF fit radii (once only) double sum = 0; for (int i = 0; i < gaussians.Count; i++) { sum += gaussians[i].R0; } double averageR = sum / gaussians.Count; residuals.Clear(); sum = 0; for (int i = 0; i < gaussians.Count; i++) { residuals.Add(averageR - gaussians[i].R0); sum += (averageR - gaussians[i].R0) * (averageR - gaussians[i].R0); } double stdDev = Math.Sqrt(sum) / gaussians.Count; if (EXCLUDE_BAD_RESIDUALS) { for (int i = residuals.Count - 1; i >= 0; i--) { if (Math.Abs(residuals[i]) > 6 * stdDev) { intencities.RemoveAt(i); magnitudes.RemoveAt(i); colours.RemoveAt(i); stars.RemoveAt(i); gaussians.RemoveAt(i); saturatedFlags.RemoveAt(i); } } } double maxResidual = Math.Max(0.1, TangraConfig.Settings.Photometry.MaxResidualStellarMags); for (int itter = 1; itter <= MAX_ITERR; itter++) { residuals.Clear(); SafeMatrix A = new SafeMatrix(intencities.Count, 3); SafeMatrix X = new SafeMatrix(intencities.Count, 1); int idx = 0; for (int i = 0; i < intencities.Count; i++) { A[idx, 0] = magnitudes[i]; A[idx, 1] = colours[i]; A[idx, 2] = 1; X[idx, 0] = -2.5 * Math.Log10(intencities[i]); idx++; } SafeMatrix a_T = A.Transpose(); SafeMatrix aa = a_T * A; SafeMatrix aa_inv = aa.Inverse(); SafeMatrix bx = (aa_inv * a_T) * X; double Ka = bx[0, 0]; double Kb = bx[1, 0]; double Kc = bx[2, 0]; // -2.5 * a * Log(Median-Intensity) = A * Mv + B * Mjk + C - b // -2.5 * Log(Median-Intensity) = Ka * Mv + Kb * Mjk + Kc // Mv = -2.5 * a * Log(Median-Intensity) - b * Mjk - c a = 1 / Ka; b = -Kb / Ka; c = -Kc / Ka; int starsExcludedThisTime = 0; if (EXCLUDE_BAD_RESIDUALS) { List<int> indexesToRemove = new List<int>(); for (int i = 0; i < intencities.Count; i++) { double computed = a * -2.5 * Math.Log10(intencities[i]) + b * colours[i] + c; double diff = Math.Abs(computed - magnitudes[i]); if (itter < MAX_ITERR) { if (Math.Abs(diff) > maxResidual) { indexesToRemove.Add(i); } } else residuals.Add(diff); } for (int i = indexesToRemove.Count - 1; i >= 0; i--) { int idxToRemove = indexesToRemove[i]; intencities.RemoveAt(idxToRemove); magnitudes.RemoveAt(idxToRemove); colours.RemoveAt(idxToRemove); stars.RemoveAt(idxToRemove); gaussians.RemoveAt(idxToRemove); saturatedFlags.RemoveAt(idxToRemove); excludedStars++; starsExcludedThisTime++; } } if (starsExcludedThisTime == 0) break; } } catch (Exception ex) { Trace.WriteLine(ex.ToString()); } return new StarMagnitudeFit( currentAstroImage, bitPix, intencities, magnitudes, colours, stars, gaussians, new List<double>(), saturatedFlags, a, b, c, encodingGamma, reverseCameraResponse, excludedStars, filter, empericalFWHM, photometryReductionMethod, photometryBackgroundMethod, psfQuadrature, psfFittingMethod, measurer, aperture); }
public ThreeStarAstrometry(AstroPlate image, Dictionary<ImagePixel, IStar> userStarIdentification, int tolerance) { if (userStarIdentification.Count != 3) throw new InvalidOperationException(); Image = image; double a0 = userStarIdentification.Values.Average(x => x.RADeg) * DEG_TO_RAD; double d0 = userStarIdentification.Values.Average(x => x.DEDeg) * DEG_TO_RAD; double corr = double.MaxValue; int attempts = 0; do { SafeMatrix AX = new SafeMatrix(3, 3); SafeMatrix X = new SafeMatrix(3, 1); SafeMatrix AY = new SafeMatrix(3, 3); SafeMatrix Y = new SafeMatrix(3, 1); int i = 0; foreach (var pixel in userStarIdentification.Keys) { IStar star = userStarIdentification[pixel]; double a = star.RADeg * DEG_TO_RAD; double d = star.DEDeg * DEG_TO_RAD; AX[i, 0] = pixel.XDouble; AX[i, 1] = pixel.YDouble; AX[i, 2] = 1; AY[i, 0] = pixel.XDouble; AY[i, 1] = pixel.YDouble; AY[i, 2] = 1; X[i, 0] = Math.Cos(d) * Math.Sin(a - a0) / (Math.Cos(d0) * Math.Cos(d) * Math.Cos(a - a0) + Math.Sin(d0) * Math.Sin(d)); Y[i, 0] = (Math.Cos(d0) * Math.Sin(d) - Math.Cos(d) * Math.Sin(d0) * Math.Cos(a - a0)) / (Math.Sin(d0) * Math.Sin(d) + Math.Cos(d0) * Math.Cos(d) * Math.Cos(a - a0)); i++; } SafeMatrix a_T = AX.Transpose(); SafeMatrix aa = a_T * AX; SafeMatrix aa_inv = aa.Inverse(); SafeMatrix bx = (aa_inv * a_T) * X; m_A = bx[0, 0]; m_B = bx[1, 0]; m_C = bx[2, 0]; a_T = AY.Transpose(); aa = a_T * AY; aa_inv = aa.Inverse(); bx = (aa_inv * a_T) * Y; m_D = bx[0, 0]; m_E = bx[1, 0]; m_F = bx[2, 0]; m_A0Rad = a0; m_D0Rad = d0; double ra_c, de_c; GetRADEFromImageCoords(Image.CenterXImage, Image.CenterYImage, out ra_c, out de_c); corr = AngleUtility.Elongation(ra_c, de_c, a0 * RAD_TO_DEG, d0 * RAD_TO_DEG) * 3600; a0 = ra_c * DEG_TO_RAD; d0 = de_c * DEG_TO_RAD; attempts++; } while (corr > tolerance && attempts < MAX_ATTEMPTS); Success = corr <= tolerance; }
protected override void ConfigureObservation(SafeMatrix A, SafeMatrix AReverse, int i) { A[i, 0] = m_StarPairs[i].x; A[i, 1] = m_StarPairs[i].y; A[i, 2] = 1; AReverse[i, 0] = m_StarPairs[i].ExpectedXTang; AReverse[i, 1] = m_StarPairs[i].ExpectedYTang; AReverse[i, 2] = 1; }
protected override void ReadSolvedReversedConstants(SafeMatrix bx, SafeMatrix by) { Const_A1 = bx[0, 0]; Const_B1 = bx[1, 0]; Const_C1 = bx[2, 0]; Const_D1 = bx[3, 0]; Const_E1 = bx[4, 0]; Const_F1 = bx[5, 0]; Const_G1 = by[0, 0]; Const_H1 = by[1, 0]; Const_K1 = by[2, 0]; Const_L1 = by[3, 0]; Const_M1 = by[4, 0]; Const_N1 = by[5, 0]; }
protected override bool ReadSolvedConstants(SafeMatrix bx, SafeMatrix by) { Const_A = bx[0, 0]; Const_B = bx[1, 0]; Const_C = bx[2, 0]; Const_D = bx[3, 0]; Const_E = bx[4, 0]; Const_F = bx[5, 0]; Const_G = by[0, 0]; Const_H = by[1, 0]; Const_K = by[2, 0]; Const_L = by[3, 0]; Const_M = by[4, 0]; Const_N = by[5, 0]; return true; }
public void Solve() { try { int dataCount = m_YValues.Count; for (int iter = NumberIterations; iter > 0; iter--) { if (iter == NumberIterations) { m_IBackground = 0.0; /* assume no backgnd intensity at first... */ m_IMax = m_YValues.Max(); m_X0 = m_XValues.Average(); double halfMax = m_IMax / 2; double x1 = double.MaxValue; double x2 = double.MinValue; double minX1 = double.MaxValue; double minX2 = double.MaxValue; for (int i = 0; i < dataCount; i++) { double diff = m_YValues[i] - halfMax; double diffAbs = Math.Abs(diff); if (m_XValues[i] < m_X0) { if (diffAbs < minX1) { minX1 = diffAbs; x1 = m_XValues[i]; } } else { if (diffAbs < minX2) { minX2 = diffAbs; x2 = m_XValues[i]; } } } double fwhm = 0.8 * (x2 - x1); m_R0 = fwhm / (2 * Math.Sqrt(Math.Log(2))); } double r0_squared = m_R0 * m_R0; SafeMatrix A = new SafeMatrix(dataCount, 4); SafeMatrix X = new SafeMatrix(dataCount, 1); int index = -1; for (int i = 0; i < dataCount; i++) { double dx = m_XValues[i] - m_X0; double fx = Math.Exp(-dx * dx / r0_squared); index++; double exp_val = fx * fx; double residual = m_IBackground + m_IMax * exp_val - m_YValues[i]; X[index, 0] = -residual; A[index, 0] = 1.0; /* slope in i0 */ A[index, 1] = exp_val; /* slope in a0 */ A[index, 2] = 2.0 * m_IMax * dx * exp_val / r0_squared; A[index, 3] = 2.0 * m_IMax * (dx * dx) * exp_val / (m_R0 * r0_squared); } SafeMatrix a_T = A.Transpose(); SafeMatrix aa = a_T * A; SafeMatrix aa_inv = aa.Inverse(); SafeMatrix Y = (aa_inv * a_T) * X; m_IBackground += Y[0, 0]; m_IMax += Y[1, 0]; for (int i = 2; i < 4; i++) { if (Y[i, 0] > 1.0) { Y[i, 0] = 1.0; } if (Y[i, 0] < -1.0) { Y[i, 0] = -1.0; } } m_X0 += Y[2, 0]; if (Y[3, 0] > m_R0 / 10.0) { Y[3, 0] = m_R0 / 10.0; } if (Y[3, 0] < -m_R0 / 10.0) { Y[3, 0] = -m_R0 / 10.0; } m_R0 += Y[3, 0]; } } catch (Exception ex) { Trace.WriteLine(ex.ToString()); } }
private void RecalculateFixedColourIndexFit() { int totalMeasuredFrames = m_Exports.SelectMany(x => x.Entries).Select(x => x.MeasuredFrames).ToList().Median(); List<TangraExportEntry> datapoints = m_Exports .SelectMany(x => x.Entries) .Where(x => !float.IsNaN(x.APASS_Sloan_r) && Math.Abs(x.APASS_Sloan_r) > 0.00001 && !float.IsNaN(x.MedianIntensity) && !float.IsNaN(x.MedianIntensity) && !float.IsNaN(x.APASS_BV_Colour) && x.MeasuredFrames > 0.95 * totalMeasuredFrames && x.SaturatedFrames == 0) .ToList(); float FIXED_COLOUR_COEFF = (float)m_FixedColourCoeff; for (int i = 0; i < datapoints.Count; i++) { datapoints[i].InstrMag = -2.5 * Math.Log10(datapoints[i].MedianIntensity) + 32 - datapoints[i].APASS_BV_Colour * FIXED_COLOUR_COEFF; datapoints[i].InstrMagErr = Math.Abs(-2.5 * Math.Log10((datapoints[i].MedianIntensity + datapoints[i].MedianIntensityError) / datapoints[i].MedianIntensity)); } datapoints = datapoints.Where(x => x.InstrMagErr < 0.2).ToList(); if (datapoints.Count < 4) return; double variance = 0; double Ka = 0; double Kb = 0; int MAX_ITTER = 2; for (int itt = 0; itt <= MAX_ITTER; itt++) { SafeMatrix A = new SafeMatrix(datapoints.Count, 2); SafeMatrix X = new SafeMatrix(datapoints.Count, 1); int idx = 0; for (int i = 0; i < datapoints.Count; i++) { A[idx, 0] = datapoints[i].InstrMag; A[idx, 1] = 1; X[idx, 0] = datapoints[i].APASS_Sloan_r; idx++; } SafeMatrix a_T = A.Transpose(); SafeMatrix aa = a_T * A; SafeMatrix aa_inv = aa.Inverse(); SafeMatrix bx = (aa_inv * a_T) * X; Ka = bx[0, 0]; Kb = bx[1, 0]; double resSum = 0; for (int i = 0; i < datapoints.Count; i++) { double computedMag = Ka * datapoints[i].InstrMag + Kb; double diff = computedMag - datapoints[i].APASS_Sloan_r; resSum += diff * diff; datapoints[i].Residual = diff; } variance = Math.Sqrt(resSum / datapoints.Count); if (itt < MAX_ITTER) datapoints.RemoveAll(x => Math.Abs(x.Residual) > 2 * variance || Math.Abs(x.Residual) > 0.2); } Trace.WriteLine(string.Format("r' + {3} * (B-V) + = {0} * M + {1} +/- {2}", Ka.ToString("0.0000"), Kb.ToString("0.0000"), variance.ToString("0.00"), FIXED_COLOUR_COEFF.ToString("0.00000"))); if (miFixedColourPlot.Checked) PlotFixedColourFitData(datapoints, Ka, Kb, variance); }
private bool LeastSquareSolve(double ra0Deg, double de0Deg, int minNumberOfStars) { int[] NUM_CONSTANTS = new int[] { 3, 6, 10 }; SafeMatrix A = new SafeMatrix(m_StarPairs.Count, NUM_CONSTANTS[(int)m_FitOrder]); SafeMatrix X = new SafeMatrix(m_StarPairs.Count, 1); SafeMatrix Y = new SafeMatrix(m_StarPairs.Count, 1); SafeMatrix AReverse = new SafeMatrix(m_StarPairs.Count, NUM_CONSTANTS[(int)m_FitOrder]); SafeMatrix XReverse = new SafeMatrix(m_StarPairs.Count, 1); SafeMatrix YReverse = new SafeMatrix(m_StarPairs.Count, 1); int numStars = 0; for (int i = 0; i < m_StarPairs.Count; i++) { m_StarPairs[i].FitInfo.UsedInSolution = false; if (m_StarPairs[i].FitInfo.ExcludedForHighResidual) continue; numStars++; m_StarPairs[i].FitInfo.UsedInSolution = true; ConfigureObservation(A, AReverse, i); X[i, 0] = m_StarPairs[i].ExpectedXTang; Y[i, 0] = m_StarPairs[i].ExpectedYTang; XReverse[i, 0] = m_StarPairs[i].x; YReverse[i, 0] = m_StarPairs[i].y; } // Insufficient stars to solve the plate if (numStars < minNumberOfStars) { if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose()) Debug.WriteLine(string.Format("Insufficient number of stars to do a fit. At least {0} stars requested.", minNumberOfStars)); return false; } SafeMatrix a_T = A.Transpose(); SafeMatrix aa = a_T * A; SafeMatrix aa_inv = aa.Inverse(); SafeMatrix bx = (aa_inv * a_T) * X; SafeMatrix by = (aa_inv * a_T) * Y; if (ReadSolvedConstants(bx, by)) { a_T = AReverse.Transpose(); aa = a_T * AReverse; aa_inv = aa.Inverse(); bx = (aa_inv * a_T) * XReverse; by = (aa_inv * a_T) * YReverse; ReadSolvedReversedConstants(bx, by); } double residualSum = 0; double residualSumArcSecRA = 0; double residualSumArcSecDE = 0; int numResiduals = 0; for (int i = 0; i < m_StarPairs.Count; i++) { double computedXTang, computedYTang; GetTangentCoordsFromImageCoords(m_StarPairs[i].x, m_StarPairs[i].y, out computedXTang, out computedYTang); m_StarPairs[i].FitInfo.ResidualXTang = m_StarPairs[i].ExpectedXTang - computedXTang; m_StarPairs[i].FitInfo.ResidualYTang = m_StarPairs[i].ExpectedYTang - computedYTang; double raComp, deComp; TangentPlane.TangentToCelestial(computedXTang, computedYTang, ra0Deg, de0Deg, out raComp, out deComp); m_StarPairs[i].FitInfo.ResidualRAArcSec = 3600.0 * AngleUtility.Elongation(m_StarPairs[i].RADeg, 0, raComp, 0); m_StarPairs[i].FitInfo.ResidualDEArcSec = 3600.0 * AngleUtility.Elongation(0, m_StarPairs[i].DEDeg, 0, deComp); if (!m_StarPairs[i].FitInfo.UsedInSolution) continue; numResiduals++; residualSum += Math.Abs(m_StarPairs[i].FitInfo.ResidualXTang * m_StarPairs[i].FitInfo.ResidualYTang); residualSumArcSecRA += m_StarPairs[i].FitInfo.ResidualRAArcSec * m_StarPairs[i].FitInfo.ResidualRAArcSec; residualSumArcSecDE += m_StarPairs[i].FitInfo.ResidualDEArcSec * m_StarPairs[i].FitInfo.ResidualDEArcSec; } Variance = residualSum / (numResiduals - 1); VarianceArcSecRA = residualSumArcSecRA / (numResiduals - 1); VarianceArcSecDE = residualSumArcSecDE / (numResiduals - 1); return true; }
public static SafeMatrix operator *(SafeMatrix A, SafeMatrix B) { if (A.ColumnCount != B.RowCount) throw new ArgumentException("Inner matrix dimensions must agree."); SafeMatrix C = new SafeMatrix(A.RowCount, B.ColumnCount); for (int i = 0; i < A.RowCount; i++) { for (int j = 0; j < B.ColumnCount; j++) { C.m_Elements[i * C.m_ColumnCount + j] = Dot(A, i, B, j); } } return C; }
public SafeMatrix Minor(int row, int col) { // THIS IS THE LOW-LEVEL SOLUTION ~ O(n^2) SafeMatrix buf = new SafeMatrix(m_RowCount - 1, m_ColumnCount - 1); int r = 0; int c = 0; for (int i = 0; i < m_RowCount; i++) { if (i != row) { for (int j = 0; j < m_ColumnCount; j++) { if (j != col) { buf.m_Elements[r * buf.m_ColumnCount + c] = m_Elements[i * m_ColumnCount + j]; c++; } } c = 0; r++; } } return buf; }
public SafeMatrix Transpose() { SafeMatrix M = new SafeMatrix(m_ColumnCount, m_RowCount); for (int i = 0; i < m_ColumnCount; i++) { for (int j = 0; j < m_RowCount; j++) { M.m_Elements[i * M.m_ColumnCount + j] = m_Elements[j * m_ColumnCount + i]; } } return M; }
public void SolveWithWeights() { if (m_XValues.Count < 3) throw new InvalidOperationException("Cannot get a linear fit from less than 3 points."); SafeMatrix A = new SafeMatrix(m_XValues.Count, 2); SafeMatrix X = new SafeMatrix(m_XValues.Count, 1); m_WeightMatrix = new SafeMatrix(m_XValues.Count, m_XValues.Count); for (int i = 0; i < m_XValues.Count; i++) { A[i, 0] = m_XValues[i]; A[i, 1] = 1; X[i, 0] = m_YValues[i]; m_WeightMatrix[i, i] = m_Weights[i]; } SafeMatrix a_T = A.Transpose(); SafeMatrix aa = (a_T * m_WeightMatrix) * A; SafeMatrix aa_inv = m_CoVarianceMatrix = aa.Inverse(); SafeMatrix bx = ((aa_inv * a_T) * m_WeightMatrix) * X; m_A = bx[0, 0]; m_B = bx[1, 0]; }
protected abstract void ConfigureObservation(SafeMatrix A, SafeMatrix AReverse, int i);
public SafeMatrix Clone() { SafeMatrix A = new SafeMatrix(m_RowCount, m_ColumnCount); for (int i = 0; i < m_MatrixSize; i++) A.m_Elements[i] = m_Elements[i]; return A; }
protected abstract bool ReadSolvedConstants(SafeMatrix bx, SafeMatrix by);
// Third Order (10 params): Z = A * x * x * x + B * x * x * y + C * y * y * x + D * y * y * y + E * x * x + F * x * y + G * y * y + H * x + I * y + J private void SolveThirdOrderFit() { SafeMatrix A = new SafeMatrix(m_ZValues.Count, 10); SafeMatrix X = new SafeMatrix(m_ZValues.Count, 1); for (int i = 0; i < m_ZValues.Count; i++) { A[i, 0] = m_XXXValues[i]; A[i, 1] = m_XXYValues[i]; A[i, 2] = m_XYYValues[i]; A[i, 3] = m_YYYValues[i]; A[i, 4] = m_XXValues[i]; A[i, 5] = m_XYValues[i]; A[i, 6] = m_YYValues[i]; A[i, 7] = m_XValues[i]; A[i, 8] = m_YValues[i]; A[i, 9] = 1; X[i, 0] = m_ZValues[i]; } SafeMatrix a_T = A.Transpose(); SafeMatrix aa = a_T*A; SafeMatrix aa_inv = aa.Inverse(); SafeMatrix bx = (aa_inv*a_T)*X; m_ThirdA = bx[0, 0]; m_ThirdB = bx[1, 0]; m_ThirdC = bx[2, 0]; m_ThirdD = bx[3, 0]; m_ThirdE = bx[4, 0]; m_ThirdF = bx[5, 0]; m_ThirdG = bx[6, 0]; m_ThirdH = bx[7, 0]; m_ThirdI = bx[8, 0]; m_ThirdJ = bx[9, 0]; m_Residuals.Clear(); double sumResidualsSQ = 0; for (int i = 0; i < m_ZValues.Count; i++) { double res = m_ZValues[i] - ComputeThirdOrderValue(m_XValues[i], m_YValues[i]); m_Residuals.Add(res); sumResidualsSQ += res * res; } m_ThirdVariance = Math.Sqrt(sumResidualsSQ/(m_ZValues.Count - 1)); }
// I(x, y) = IBackground + IStarMax1 * Exp ( -((x - X1)*(x - X1) + (y - Y1)*(y - Y1)) / (r1 * r1)) + IStarMax2 * Exp ( -((x - X2)*(x - X2) + (y - Y2)*(y - Y2)) / (r2 * r2)) private void NonLinearFit(uint[,] intensity, int x1start, int y1start, int x2start, int y2start, bool useNativeMatrix) { m_IsSolved = false; try { int full_width = (int)Math.Round(Math.Sqrt(intensity.Length)); m_MatrixSize = full_width; int half_width = full_width / 2; m_HalfWidth = half_width; switch (PSFFit.DataRange) { case PSFFittingDataRange.DataRange8Bit: m_Saturation = TangraConfig.Settings.Photometry.Saturation.Saturation8Bit; break; case PSFFittingDataRange.DataRange12Bit: m_Saturation = TangraConfig.Settings.Photometry.Saturation.Saturation12Bit; break; case PSFFittingDataRange.DataRange14Bit: m_Saturation = TangraConfig.Settings.Photometry.Saturation.Saturation14Bit; break; case PSFFittingDataRange.DataRange16Bit: m_Saturation = PSFFit.NormVal > 0 ? (uint)(TangraConfig.Settings.Photometry.Saturation.Saturation8Bit * PSFFit.NormVal / 255.0) : TangraConfig.Settings.Photometry.Saturation.Saturation16Bit; break; default: m_Saturation = TangraConfig.Settings.Photometry.Saturation.Saturation8Bit; break; } int nonSaturatedPixels = 0; double IBackground = 0; double r1 = 4.0; double r2 = 4.0; double IStarMax1 = 0; double IStarMax2 = 0; double found_x1 = x1start; double found_y1 = y1start; double found_x2 = x2start; double found_y2 = y2start; for (int iter = NumberIterations; iter > 0; iter--) { if (iter == NumberIterations) { uint zval = 0; IBackground = 0.0; /* assume no backgnd intensity at first... */ for (int i = 0; i < full_width; i++) { for (int j = 0; j < full_width; j++) { if (intensity[i, j] > zval) zval = intensity[i, j]; if (intensity[i, j] < m_Saturation) nonSaturatedPixels++; } } IStarMax1 = (double)zval - IBackground; IStarMax2 = IStarMax1; } double[] dx1 = new double[full_width]; double[] dy1 = new double[full_width]; double[] fx1 = new double[full_width]; double[] fy1 = new double[full_width]; double[] dx2 = new double[full_width]; double[] dy2 = new double[full_width]; double[] fx2 = new double[full_width]; double[] fy2 = new double[full_width]; double r1_squared = r1 * r1; double r2_squared = r2 * r2; for (int i = 0; i < full_width; i++) { dx1[i] = (double)i - found_x1; fx1[i] = Math.Exp(-dx1[i] * dx1[i] / r1_squared); dy1[i] = (double)i - found_y1; fy1[i] = Math.Exp(-dy1[i] * dy1[i] / r1_squared); dx2[i] = (double)i - found_x2; fx2[i] = Math.Exp(-dx2[i] * dx2[i] / r2_squared); dy2[i] = (double)i - found_y2; fy2[i] = Math.Exp(-dy2[i] * dy2[i] / r2_squared); } SafeMatrix A = new SafeMatrix(nonSaturatedPixels, 9); SafeMatrix X = new SafeMatrix(nonSaturatedPixels, 1); int index = -1; for (int i = 0; i < full_width; i++) { for (int j = 0; j < full_width; j++) { double zval = intensity[i, j]; if (m_BackgroundModel != null) zval -= m_BackgroundModel.ComputeValue(i, j); if (zval < m_Saturation) { index++; double exp_val1 = fx1[i] * fy1[j]; double exp_val2 = fx2[i] * fy2[j]; double residual = IBackground + IStarMax1 * exp_val1 + IStarMax2 * exp_val2 - zval; X[index, 0] = -residual; A[index, 0] = 1.0; /* slope in i0 */ A[index, 1] = exp_val1; A[index, 2] = exp_val2; A[index, 3] = 2.0 * IStarMax1 * dx1[i] * exp_val1 / r1_squared; A[index, 4] = 2.0 * IStarMax1 * dy1[j] * exp_val1 / r1_squared; A[index, 5] = 2.0 * IStarMax2 * dx2[i] * exp_val2 / r2_squared; A[index, 6] = 2.0 * IStarMax2 * dy2[j] * exp_val2 / r2_squared; A[index, 7] = 2.0 * IStarMax1 * (dx1[i] * dx1[i] + dy1[j] * dy1[j]) * exp_val1 / (r1 * r1_squared); A[index, 8] = 2.0 * IStarMax2 * (dx2[i] * dx2[i] + dy2[j] * dy2[j]) * exp_val2 / (r2 * r2_squared); } } } SafeMatrix Y; if (useNativeMatrix) { Y = TangraModelCore.SolveLinearSystemFast(A, X); } else { SafeMatrix a_T = A.Transpose(); SafeMatrix aa = a_T * A; SafeMatrix aa_inv = aa.Inverse(); Y = (aa_inv * a_T) * X; } /* we need at least 9 unsaturated pixels to solve 8 params */ if (nonSaturatedPixels > 9) /* Request all pixels to be good! */ { IBackground += Y[0, 0]; IStarMax1 += Y[1, 0]; IStarMax2 += Y[2, 0]; for (int i = 3; i < 7; i++) { if (Y[i, 0] > 1.0) Y[i, 0] = 1.0; if (Y[i, 0] < -1.0) Y[i, 0] = -1.0; } found_x1 += Y[3, 0]; found_y1 += Y[4, 0]; found_x2 += Y[5, 0]; found_y2 += Y[6, 0]; if (Y[7, 0] > r1 / 10.0) Y[7, 0] = r1 / 10.0; if (Y[7, 0] < -r1 / 10.0) Y[7, 0] = -r1 / 10.0; r1 += Y[7, 0]; if (Y[8, 0] > r2 / 10.0) Y[8, 0] = r2 / 10.0; if (Y[8, 0] < -r2 / 10.0) Y[8, 0] = -r2 / 10.0; r2 += Y[8, 0]; } else { m_IsSolved = false; return; } } m_IsSolved = true; m_IBackground = IBackground; m_IStarMax1 = IStarMax1; m_IStarMax2 = IStarMax2; m_X1 = found_x1; m_Y1 = found_y1; m_R1 = r1; m_X2 = found_x2; m_Y2 = found_y2; m_R2 = r2; // NOTE: The brighter object becomes the object to be tracked/returned as main object if (m_IStarMax1 > m_IStarMax2) { m_IStarMax = IStarMax1; m_X0 = found_x1; m_Y0 = found_y1; m_R0 = r1; } else { m_IStarMax = IStarMax2; m_X0 = found_x2; m_Y0 = found_y2; m_R0 = r2; } m_Residuals = new double[full_width, full_width]; for (int x = 0; x < full_width; x++) for (int y = 0; y < full_width; y++) { m_Residuals[x, y] = intensity[x, y] - GetPSFValueInternal(x, y); } } catch (DivideByZeroException) { } }
protected override bool ReadSolvedConstants(SafeMatrix bx, SafeMatrix by) { Const_A = bx[0, 0]; Const_B = bx[1, 0]; Const_C = bx[2, 0]; Const_D = by[0, 0]; Const_E = by[1, 0]; Const_F = by[2, 0]; Const_A1 = Const_E / (Const_E * Const_A - Const_B * Const_D); Const_B1 = -Const_B / (Const_E * Const_A - Const_B * Const_D); Const_C1 = (Const_B * Const_F - Const_C * Const_E) / (Const_E * Const_A - Const_B * Const_D); Const_D1 = Const_D / (Const_B * Const_D - Const_A * Const_E); Const_E1 = -Const_A / (Const_B * Const_D - Const_A * Const_E); Const_F1 = (Const_A * Const_F - Const_C * Const_D) / (Const_B * Const_D - Const_A * Const_E); return false; }
/// <summary> /// Inverts square matrix as long as det != 0. /// </summary> /// <returns>Inverse of matrix.</returns> public SafeMatrix Inverse() { if (!this.IsSquare()) throw new InvalidOperationException("Cannot invert non-square matrix."); double det = this.Determinant(); if (det == 0) throw new InvalidOperationException("Cannot invert (nearly) singular matrix."); SafeMatrix buf = new SafeMatrix(m_ColumnCount, m_ColumnCount); for (int i = 0; i < m_ColumnCount; i++) { for (int j = 0; j < m_ColumnCount; j++) { buf.m_Elements[i * buf.m_ColumnCount + j] = (Math.Pow(-1, i + j) * this.Minor(j, i).Determinant()) / det; } } return buf; }
protected override void ReadSolvedReversedConstants(SafeMatrix bx, SafeMatrix by) { }
// First Order (3 params): Z = A * x + B * y + C private void SolveFirstOrderFit() { SafeMatrix A = new SafeMatrix(m_ZValues.Count, 3); SafeMatrix X = new SafeMatrix(m_ZValues.Count, 1); for (int i = 0; i < m_ZValues.Count; i++) { A[i, 0] = m_XValues[i]; A[i, 1] = m_YValues[i]; A[i, 2] = 1; X[i, 0] = m_ZValues[i]; } SafeMatrix a_T = A.Transpose(); SafeMatrix aa = a_T * A; SafeMatrix aa_inv = aa.Inverse(); SafeMatrix bx = (aa_inv * a_T) * X; m_FirstA = bx[0, 0]; m_FirstB = bx[1, 0]; m_FirstC = bx[2, 0]; m_Residuals.Clear(); double sumResidualsSQ = 0; for (int i = 0; i < m_ZValues.Count; i++) { double res = m_ZValues[i] - ComputeFirstOrderValue(m_XValues[i], m_YValues[i]); m_Residuals.Add(res); sumResidualsSQ += res * res; } m_FirstVariance = Math.Sqrt(sumResidualsSQ / (m_ZValues.Count - 1)); }
private void CalculateGagnitudeFit(Dictionary<IStar, double> measurements, double fixedColourCoeff) { List<MagFitEntry> datapoints = new List<MagFitEntry>(); foreach (IStar star in measurements.Keys) { UCAC4Entry ucac4 = (UCAC4Entry) star; if (!double.IsNaN(ucac4.Mag_r) && Math.Abs(ucac4.Mag_r) > 0.00001 && !double.IsNaN(ucac4.MagB) && !double.IsNaN(ucac4.MagV)) { datapoints.Add(new MagFitEntry() { APASS_Sloan_r = ucac4.Mag_r, APASS_BV_Colour = ucac4.MagB - ucac4.MagV, MedianIntensity = measurements[star], MedianIntensityError = 0.05 * measurements[star] }); } } float FIXED_COLOUR_COEFF = (float)fixedColourCoeff; for (int i = 0; i < datapoints.Count; i++) { datapoints[i].InstrMag = -2.5 * Math.Log10(datapoints[i].MedianIntensity) + 32 - datapoints[i].APASS_BV_Colour * FIXED_COLOUR_COEFF; datapoints[i].InstrMagErr = Math.Abs(-2.5 * Math.Log10((datapoints[i].MedianIntensity + datapoints[i].MedianIntensityError) / datapoints[i].MedianIntensity)); } datapoints = datapoints.Where(x => !double.IsNaN(x.InstrMag) && x.InstrMagErr < 0.2).ToList(); if (datapoints.Count < 4) return; double variance = 0; double Ka = 0; double Kb = 0; int MAX_ITTER = 2; for (int itt = 0; itt <= MAX_ITTER; itt++) { SafeMatrix A = new SafeMatrix(datapoints.Count, 2); SafeMatrix X = new SafeMatrix(datapoints.Count, 1); int idx = 0; for (int i = 0; i < datapoints.Count; i++) { A[idx, 0] = datapoints[i].InstrMag; A[idx, 1] = 1; X[idx, 0] = datapoints[i].APASS_Sloan_r; idx++; } SafeMatrix a_T = A.Transpose(); SafeMatrix aa = a_T * A; SafeMatrix aa_inv = aa.Inverse(); SafeMatrix bx = (aa_inv * a_T) * X; Ka = bx[0, 0]; Kb = bx[1, 0]; double resSum = 0; for (int i = 0; i < datapoints.Count; i++) { double computedMag = Ka * datapoints[i].InstrMag + Kb; double diff = computedMag - datapoints[i].APASS_Sloan_r; resSum += diff * diff; datapoints[i].Residual = diff; } variance = Math.Sqrt(resSum / datapoints.Count); if (itt < MAX_ITTER) datapoints.RemoveAll(x => Math.Abs(x.Residual) > 2 * variance || Math.Abs(x.Residual) > 0.2); } Trace.WriteLine(string.Format("r' + {3} * (B-V) + = {0} * M + {1} +/- {2}", Ka.ToString("0.0000"), Kb.ToString("0.0000"), variance.ToString("0.00"), FIXED_COLOUR_COEFF.ToString("0.00000"))); }
public static double Dot(SafeMatrix v, int vRow, SafeMatrix w, int wCol) { if (v.ColumnCount != w.RowCount) throw new ArgumentException("Vectors must be of the same length."); double buf = 0; for (int i = 0; i < v.ColumnCount; i++) { buf += v.m_Elements[vRow * v.m_ColumnCount + i] * w.m_Elements[i * w.m_ColumnCount + wCol]; } return buf; }