Example #1
0
        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);
        }
Example #2
0
        /// <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);
        }
Example #3
0
        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];
        }
Example #4
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;
            }
        }
Example #5
0
        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);
        }
Example #6
0
        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);
        }
Example #7
0
        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;
        }
Example #8
0
        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);
        }
Example #9
0
        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);
        }
Example #10
0
        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);
        }
Example #11
0
        /// <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;
        }
Example #12
0
        // 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)
            { }
        }
Example #13
0
        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);
        }
Example #14
0
        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);
                }
            }
        }
Example #15
0
        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);
                }
            }
        }
Example #16
0
 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;
            }
        }
Example #18
0
        public static StarMagnitudeFit PerformFit(
			IAstrometryController astrometryController,
			IVideoController videoController,
			int bitPix,
            uint maxSignalValue,
			FitInfo astrometricFit,
			TangraConfig.PhotometryReductionMethod photometryReductionMethod,
			TangraConfig.PsfQuadrature psfQuadrature,
			TangraConfig.PsfFittingMethod psfFittingMethod,
			TangraConfig.BackgroundMethod photometryBackgroundMethod,
			TangraConfig.PreProcessingFilter filter,
			List<IStar> catalogueStars,
            Guid magnitudeBandId,
			float encodingGamma,
			TangraConfig.KnownCameraResponse reverseCameraResponse,
			float? aperture,
			float? annulusInnerRadius,
			int? annulusMinPixels,
			ref float empericalPSFR0)
        {
            uint saturatedValue = TangraConfig.Settings.Photometry.Saturation.GetSaturationForBpp(bitPix, maxSignalValue);

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

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

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

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

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

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

            int matSize = CorePhotometrySettings.Default.MatrixSizeForCalibratedPhotometry;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                        idx++;
                    }

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

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

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

                    int starsExcludedThisTime = 0;

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

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

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

                            excludedStars++;
                            starsExcludedThisTime++;
                        }
                    }

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

            return new StarMagnitudeFit(
                currentAstroImage,
                bitPix,
                intencities, magnitudes, colours, stars, gaussians, new List<double>(),
                saturatedFlags, a, b, c, encodingGamma, reverseCameraResponse, excludedStars, filter, empericalFWHM,
                photometryReductionMethod, photometryBackgroundMethod, psfQuadrature, psfFittingMethod, measurer, aperture);
        }
Example #19
0
        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;
        }
Example #23
0
        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());
            }
        }
Example #24
0
        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);
        }
Example #25
0
        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;
        }
Example #26
0
        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;
        }
Example #27
0
        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;
        }
Example #28
0
        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;
        }
Example #29
0
        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];
        }
Example #30
0
 protected abstract void ConfigureObservation(SafeMatrix A, SafeMatrix AReverse, int i);
Example #31
0
        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;
        }
Example #32
0
 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));
        }
Example #34
0
        // 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;
        }
Example #36
0
        /// <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")));
        }
Example #40
0
        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;
        }