Beispiel #1
0
        private void PresentResults(int targetId, KweeVanWoerdenResult result, PolynomialFitResult polyResult = null)
        {
            var frmResults = new frmResults();

            frmResults.Results       = result;
            frmResults.PolyResults   = polyResult;
            frmResults.TangraHost    = m_TangraHost;
            frmResults.TargetId      = targetId;
            frmResults.StartPosition = FormStartPosition.CenterParent;
            frmResults.ShowDialog(m_TangraHost.ParentWindow);
        }
Beispiel #2
0
        private void ExecuteWithSimulatedData()
        {
            double[] times;
            double[] varStar;
            double[] varSky;
            double[] compStar;
            double[] compSky;


            int dataPoints = 0;

            byte[] bytes           = LoadBytesFromEmbeddedResource("Input_Observations.bin");
            double jdAtUtcMidnight = 2456967.1234567;

            using (var memStr = new MemoryStream(bytes))
                using (var rdr = new BinaryReader(memStr))
                {
                    dataPoints = rdr.ReadInt32();

                    times    = new double[dataPoints];
                    varStar  = new double[dataPoints];
                    varSky   = new double[dataPoints];
                    compStar = new double[dataPoints];
                    compSky  = new double[dataPoints];

                    for (int i = 0; i < dataPoints; i++)
                    {
                        times[i]    = rdr.ReadDouble() * 86400.0;              // Convert from days to seconds
                        varStar[i]  = rdr.ReadDouble();
                        varSky[i]   = rdr.ReadDouble();
                        compStar[i] = rdr.ReadDouble();
                        compSky[i]  = rdr.ReadDouble();
                    }
                }

            KweeVanWoerdenResult result = Kwee_van_Woerden(dataPoints, jdAtUtcMidnight, times, varStar, varSky, compStar, compSky, false);

            PolynomialFitResult polyResult = PolynomialFit(dataPoints, jdAtUtcMidnight, times, varStar, varSky, compStar, compSky, (int)result.Start_Light_Curve_Obs_Index, (int)result.Stop_Light_Curve_Obs_Index, result.Time_Of_Minimum);

            PresentResults(0, result, polyResult);
        }
 private void PresentResults(int targetId, KweeVanWoerdenResult result, PolynomialFitResult polyResult = null)
 {
     var frmResults = new frmResults();
     frmResults.Results = result;
     frmResults.PolyResults = polyResult;
     frmResults.TangraHost = m_TangraHost;
     frmResults.TargetId = targetId;
     frmResults.StartPosition = FormStartPosition.CenterParent;
     frmResults.ShowDialog(m_TangraHost.ParentWindow);
 }
        private KweeVanWoerdenResult Kwee_van_Woerden(
            long Number_Obs, double Time_First_JD, 
            double[] SecondsFromTimeFirstJD, double[] Variable_Star_DN, double[] Variable_Sky_DN, double[] Comparison_Star_DN, double[] Comparison_Sky_DN,
            bool fineGranedBins)
        {
            long BASE_NUMBER = fineGranedBins ? 1000 : 100;
            /* Constant parameter */
            long         Normal_Points = BASE_NUMBER + 1;         /* Number of evenly spaced data pairs used in the analysis */
            long         Normal_Point_Middle;                     /* Index of the middle element of the normal point array */

            /* Luminosity values */
            double[]     Luminosity_Ratio;						  /* Variable luminosity divided by comparison luminosity */
            double       Luminosity_Normal_Sum;                   /* Summation of luminosities for normal point computation */
            long         Luminosity_Normal_Count;                 /* Counter for data points in one normal point */
            double[] Luminosity_Normal = new double[BASE_NUMBER + 2];     /* Normalized luminosities */

            /* Time values */
            double       Time_Interval;                           /* Time interval between observations */
            double       Time_Start, Time_Stop;                   /* Limits for normal points */
            double[] Time_Normal = new double[BASE_NUMBER + 2];           /* Times corresponding to normal points */

            /* Symmetry analysis */
            double       Luminosity_Faintest;                     /* Faintest normalized luminosity */
            long         Luminosity_Faintest_Index;               /* Index of the faintest normalized luminosity */
            long         Start_Light_Curve;                       /* Start element of normalized light curve to analyze */
            //long         Middle_Light_Curve;                      /* Middle element of normalized light curve to analyze */
            long         Stop_Light_Curve;                        /* Stop element of normalized light curve to analyze */
            long         Start_Sum_Squares;                       /* Start element of the sum-of-squares array */
            long         Stop_Sum_Squares;                        /* Stop element of the sum-of-squares array */
            double       Sum_Of_Squares;                          /* Sum of squares across a time of symmetry */
            long[] Sum_Of_Squares_Count = new long[BASE_NUMBER + 2];    /* Number of squares accumulated */
            double[] Sum_Of_Squares_Mean = new double[BASE_NUMBER + 2];   /* Sum of squares divided by count */
            long         Sum_Of_Squares_Smallest_Index;           /* Index of the smallest sum of squares */
            double       Sum_Of_Squares_Smallest;                 /* Smallest sum of squares */

            /* Time of minimum and uncertainty */
            double[]     Quad = new double[4];                    /* Inputs to the quadratic equation taken from the sums of squares */
            double       A, B, C;                                 /* Intermediate values for quadratic equation */
            double       T0;                                      /* Time of symmetry */
            double       T0_Uncertainty;                          /* Time of symmetry uncertainty */
            //double       Time_Of_Minimum;                         /* Time of minimum light */
            //double       Time_Of_Minimum_Uncertainty;             /* Time of minimum light uncertainty */

            /* Loop indices */
            long         i, j;                                    /* Loop indices */

            var rv = new KweeVanWoerdenResult()
            {
                NumberObservations = Number_Obs
            };

            rv.Observations_File.Add("                Time     Luminosity_Ratio     Variable_Star_DN      Variable_Sky_DN   Comparison_Star_DN    Comparison_Sky_DN");
            rv.Normals_File.Add("                Time    Luminosity_Ratio");

            double[] Time = new double[Number_Obs];
            for (int k = 0; k < Number_Obs; k++)
                Time[k] = SecondsFromTimeFirstJD[k] / 86400.0;

            Luminosity_Ratio = new double[Number_Obs];
            /* Determine luminosity ratios */
            for (i = 0; i < Number_Obs; i++)
            {
                Luminosity_Ratio[i] = ( Variable_Star_DN[i] - Variable_Sky_DN[i] ) / ( Comparison_Star_DN[i] - Comparison_Sky_DN[i] );

                rv.Observations_File.Add(
                    Time[i].ToString("#########0.000000").PadLeft(20) + " " +
                    Luminosity_Ratio[i].ToString("#########0.000000").PadLeft(20) + " " +
                    Variable_Star_DN[i].ToString("#########0.000000").PadLeft(20) + " " +
                    Variable_Sky_DN[i].ToString("#########0.000000").PadLeft(20) + " " +
                    Comparison_Star_DN[i].ToString("#########0.000000").PadLeft(20) + " " +
                    Comparison_Sky_DN[i].ToString("#########0.000000").PadLeft(20));
            }

            bool hasEmptyBins = false;

            /* Compute normal point times and luminosities */
            Time_Interval = ( Time[Number_Obs - 1] - Time[0] ) / (float)Normal_Points;
            for (i = 0; i < Normal_Points; i++)
            {
                Time_Start = Time[0] + i * Time_Interval;
                Time_Normal[i] = Time_Start + Time_Interval / 2.0;
                Time_Stop = Time_Start + Time_Interval;
                Luminosity_Normal_Sum = 0.0;
                Luminosity_Normal_Count = 0;
                for (j = 0; j < Number_Obs; j++ )
                {
                    if ( ( Time[j] >= Time_Start ) && ( Time[j] < Time_Stop) )
                    {
                        Luminosity_Normal_Sum = Luminosity_Normal_Sum + Luminosity_Ratio[j];
                        Luminosity_Normal_Count = Luminosity_Normal_Count + 1;
                    }
                }

                if ( Luminosity_Normal_Count > 0 )
                {
                    Luminosity_Normal[i] = Luminosity_Normal_Sum / (float)Luminosity_Normal_Count;
                    rv.Normals_File.Add(Time_Normal[i].ToString("#########0.000000").PadLeft(20) + " " + Luminosity_Normal[i].ToString("#########0.000000").PadLeft(20));
                }
                else
                {
                    hasEmptyBins = true;
                    Luminosity_Normal[i] = double.NaN;
                }
            }

            if (hasEmptyBins)
            {
                for (i = 0; i < Normal_Points; i++)
                {
                    bool isEmptyBin = double.IsNaN(Luminosity_Normal[i]);
                    if (isEmptyBin)
                    {
                        double? prevBin2 = i <= 1 ? (double?)null : Luminosity_Normal[i - 2];
                        double? prevBin = i == 0 ? (double?) null : Luminosity_Normal[i - 1];
                        var emptyBins = new List<double>();
                        long k = i;
                        while (k < Normal_Points && double.IsNaN(Luminosity_Normal[k]))
                        {
                            k++;
                            emptyBins.Add(double.NaN);
                        }
                        double? nextBin = k == Normal_Points ? (double?)null : Luminosity_Normal[k];
                        double? nextBin2 = k + 1 < Normal_Points || k + 1 >= Luminosity_Normal.Length ? (double?)null : Luminosity_Normal[k + 1];

                        if ((prevBin == null && nextBin2 == null) || (prevBin2 == null && nextBin == null))
                        {
                            rv.ErrorMessage = "Too many empty bins!";
                            return rv;
                        }

                        double step = 0;
                        if (prevBin == null)
                            step = nextBin2.Value - nextBin.Value;
                        else if (nextBin == null)
                            step = prevBin.Value - prevBin2.Value;
                        else
                            step = (nextBin.Value - prevBin.Value) / (1 + emptyBins.Count);

                        for (int l = 0; l < emptyBins.Count; l++)
                        {
                            Luminosity_Normal[i + l] = prevBin.Value + l * step;
                        }
                    }
                }
            }

            rv.Buckets.Clear();
            rv.Buckets.AddRange(Luminosity_Normal);

            /* Locate the faintest luminosity */
            Luminosity_Faintest = 1000000000.0;
            Luminosity_Faintest_Index = 0;
            for (i = 0; i < Normal_Points; i++)
            {
                if ( Luminosity_Normal[i] < Luminosity_Faintest )
                {
                    Luminosity_Faintest_Index = i;
                    Luminosity_Faintest = Luminosity_Normal[i];
                }
            }

            /* Set the limits of the light curve to be symmetrical around the faintest luminosity */
            Start_Light_Curve = 0;
            Stop_Light_Curve = Normal_Points - 1;
            Normal_Point_Middle = Normal_Points / 2;
            if ( Luminosity_Faintest_Index < Normal_Point_Middle ) { Stop_Light_Curve = 2 * Luminosity_Faintest_Index; }
            if ( Luminosity_Faintest_Index > Normal_Point_Middle ) { Start_Light_Curve = 2 * Luminosity_Faintest_Index - Normal_Points + 1; }
            rv.IncludedObservations = 100 * (Stop_Light_Curve - Start_Light_Curve - 2) / BASE_NUMBER;

            rv.Start_Light_Curve = Start_Light_Curve;
            rv.Stop_Light_Curve = Stop_Light_Curve;

            double startTime = Time[0] + Start_Light_Curve * Time_Interval;
            double stopTime = Time[0] + (Stop_Light_Curve + 1) * Time_Interval;
            long startIndex = 0;
            long stopIndex = Number_Obs - 1;
            for (int k = 0; k < Number_Obs; k++)
            {
                if (Start_Light_Curve > 0 && Time[k] <= startTime) startIndex = k + 1;
                if (Stop_Light_Curve < Number_Obs - 1 && k > 1 && Time[k] > stopTime && Time[k - 1] < stopTime) stopIndex = k - 1;
            }
            rv.Start_Light_Curve_Obs_Index = startIndex;
            rv.Stop_Light_Curve_Obs_Index = stopIndex;

            /* Compute the normalized sums of squares of luminosity differences across an array of times */
            Start_Sum_Squares = Start_Light_Curve + 1;
            Stop_Sum_Squares  = Stop_Light_Curve  - 1;
            for (i = Start_Sum_Squares; i <= Stop_Sum_Squares; i++)
            {
                Sum_Of_Squares = 0.0;
                Sum_Of_Squares_Count[i] = 0;

                for (j = 0; j < Normal_Points; j++)
                {
                    if ( i - j >= 0 && i + j < Normal_Points )
                    {
                        Sum_Of_Squares = Sum_Of_Squares + Math.Pow(Luminosity_Normal[i-j] - Luminosity_Normal[i+j], 2);
                        Sum_Of_Squares_Count[i] = Sum_Of_Squares_Count[i] + 1;
                    }
                }

                Sum_Of_Squares_Mean[i] = Sum_Of_Squares / (float) Sum_Of_Squares_Count[i];
            }

            rv.Sum_Of_Squares_Count.Clear();
            rv.Sum_Of_Squares_Count.AddRange(Sum_Of_Squares_Count);
            rv.Sum_Of_Squares_Mean.Clear();
            rv.Sum_Of_Squares_Mean.AddRange(Sum_Of_Squares_Mean);

            /* Find the smallest normalized sum of squares */
            Sum_Of_Squares_Smallest = 1000000000;
            Sum_Of_Squares_Smallest_Index = 0;
            for (i = Start_Sum_Squares; i <= Stop_Sum_Squares; i++)
            {
                if ( Sum_Of_Squares_Mean[i] < Sum_Of_Squares_Smallest )
                {
                    /* Must also have a reasonable sample of points */
                    if ( Sum_Of_Squares_Count[i] > Normal_Points / 10 )
                    {
                        Sum_Of_Squares_Smallest_Index = i;
                        Sum_Of_Squares_Smallest = Sum_Of_Squares_Mean[i];
                    }
                }
            }

            rv.Sum_Of_Squares_Smallest_Index = Sum_Of_Squares_Smallest_Index;

            if (Sum_Of_Squares_Smallest_Index - 2 < 0 ||
                Sum_Of_Squares_Smallest_Index + 2 > Sum_Of_Squares_Mean.Length - 1)
            {
                rv.ErrorMessage = string.Format("Cannot locate the smallest normalized sum of squares (Index = {0})", Sum_Of_Squares_Smallest_Index);
                return rv;
            }

            /* Solve the quadratic equation */
            for (i = 0; i <= 3; i++) {
                Quad[i] = Sum_Of_Squares_Mean[Sum_Of_Squares_Smallest_Index+i-2];
            }

            A = -Quad[2] + ( Quad[3] + Quad[1] ) / 2.0;
            B = -3.0 * A + Quad[2] - Quad[1];
            C = Quad[1] - A - B;

            /* Calculate the time of minimum and uncertainty */
            T0 = -B / ( 2.0 * A );
            T0_Uncertainty = Math.Sqrt((4.0 * A * C - B * B) / (4.0 * A * A) / ((float)Normal_Points / 4.0 - 1.0));

            rv.T0 = T0;
            rv.T0_Uncertainty = T0_Uncertainty;
            rv.Time_Of_Minimum = Time_Normal[1] + ((Sum_Of_Squares_Smallest_Index - 1) + (T0 - 2.0)) * Time_Interval;
            rv.Time_Of_Minimum_JD = Time_First_JD + rv.Time_Of_Minimum;
            rv.Time_Of_Minimum_Uncertainty = T0_Uncertainty * Time_Interval;
            rv.Success = true;

            rv.Summary_File.Add(string.Format("      Time_First               Number_Obs"));
            rv.Summary_File.Add(Time_First_JD.ToString("#########0.000000").PadLeft(20) + " " + Number_Obs.ToString("#########0").PadLeft(20));
            rv.Summary_File.Add(string.Format("\n               Time of minimum: \n"));
            rv.Summary_File.Add(string.Format("      Bins-Quadratic          Uncertainty"));
            rv.Summary_File.Add(T0.ToString("#########0.000000").PadLeft(20) + " " + T0_Uncertainty.ToString("#########0.000000").PadLeft(20));
            rv.Summary_File.Add(string.Format("      From Time_First         Uncertainty"));
            rv.Summary_File.Add(rv.Time_Of_Minimum.ToString("#########0.000000").PadLeft(20) + " " + rv.Time_Of_Minimum_Uncertainty.ToString("#########0.000000").PadLeft(20));
            rv.Summary_File.Add(string.Format("      Absolute                Uncertainty"));
            rv.Summary_File.Add(rv.Time_Of_Minimum_JD.ToString("#########0.000000").PadLeft(20) + " " + rv.Time_Of_Minimum_Uncertainty.ToString("#########0.000000").PadLeft(20));

            /* Finish */
            return rv;
        }
Beispiel #5
0
        private KweeVanWoerdenResult Kwee_van_Woerden(
            long Number_Obs, double Time_First_JD,
            double[] SecondsFromTimeFirstJD, double[] Variable_Star_DN, double[] Variable_Sky_DN, double[] Comparison_Star_DN, double[] Comparison_Sky_DN,
            bool fineGranedBins)
        {
            long BASE_NUMBER = fineGranedBins ? 1000 : 100;
            /* Constant parameter */
            long Normal_Points = BASE_NUMBER + 1;                             /* Number of evenly spaced data pairs used in the analysis */
            long Normal_Point_Middle;                                         /* Index of the middle element of the normal point array */

            /* Luminosity values */
            double[] Luminosity_Ratio;                                        /* Variable luminosity divided by comparison luminosity */
            double   Luminosity_Normal_Sum;                                   /* Summation of luminosities for normal point computation */
            long     Luminosity_Normal_Count;                                 /* Counter for data points in one normal point */

            double[] Luminosity_Normal = new double[BASE_NUMBER + 2];         /* Normalized luminosities */

            /* Time values */
            double Time_Interval;                                             /* Time interval between observations */
            double Time_Start, Time_Stop;                                     /* Limits for normal points */

            double[] Time_Normal = new double[BASE_NUMBER + 2];               /* Times corresponding to normal points */

            /* Symmetry analysis */
            double Luminosity_Faintest;                                       /* Faintest normalized luminosity */
            long   Luminosity_Faintest_Index;                                 /* Index of the faintest normalized luminosity */
            long   Start_Light_Curve;                                         /* Start element of normalized light curve to analyze */
            //long         Middle_Light_Curve;                      /* Middle element of normalized light curve to analyze */
            long   Stop_Light_Curve;                                          /* Stop element of normalized light curve to analyze */
            long   Start_Sum_Squares;                                         /* Start element of the sum-of-squares array */
            long   Stop_Sum_Squares;                                          /* Stop element of the sum-of-squares array */
            double Sum_Of_Squares;                                            /* Sum of squares across a time of symmetry */

            long[]   Sum_Of_Squares_Count = new long[BASE_NUMBER + 2];        /* Number of squares accumulated */
            double[] Sum_Of_Squares_Mean  = new double[BASE_NUMBER + 2];      /* Sum of squares divided by count */
            long     Sum_Of_Squares_Smallest_Index;                           /* Index of the smallest sum of squares */
            double   Sum_Of_Squares_Smallest;                                 /* Smallest sum of squares */

            /* Time of minimum and uncertainty */
            double[] Quad = new double[4];                                    /* Inputs to the quadratic equation taken from the sums of squares */
            double   A, B, C;                                                 /* Intermediate values for quadratic equation */
            double   T0;                                                      /* Time of symmetry */
            double   T0_Uncertainty;                                          /* Time of symmetry uncertainty */
            //double       Time_Of_Minimum;                         /* Time of minimum light */
            //double       Time_Of_Minimum_Uncertainty;             /* Time of minimum light uncertainty */

            /* Loop indices */
            long i, j;                                                        /* Loop indices */

            var rv = new KweeVanWoerdenResult()
            {
                NumberObservations = Number_Obs
            };

            rv.Observations_File.Add("                Time     Luminosity_Ratio     Variable_Star_DN      Variable_Sky_DN   Comparison_Star_DN    Comparison_Sky_DN");
            rv.Normals_File.Add("                Time    Luminosity_Ratio");


            double[] Time = new double[Number_Obs];
            for (int k = 0; k < Number_Obs; k++)
            {
                Time[k] = SecondsFromTimeFirstJD[k] / 86400.0;
            }

            Luminosity_Ratio = new double[Number_Obs];
            /* Determine luminosity ratios */
            for (i = 0; i < Number_Obs; i++)
            {
                Luminosity_Ratio[i] = (Variable_Star_DN[i] - Variable_Sky_DN[i]) / (Comparison_Star_DN[i] - Comparison_Sky_DN[i]);

                rv.Observations_File.Add(
                    Time[i].ToString("#########0.000000").PadLeft(20) + " " +
                    Luminosity_Ratio[i].ToString("#########0.000000").PadLeft(20) + " " +
                    Variable_Star_DN[i].ToString("#########0.000000").PadLeft(20) + " " +
                    Variable_Sky_DN[i].ToString("#########0.000000").PadLeft(20) + " " +
                    Comparison_Star_DN[i].ToString("#########0.000000").PadLeft(20) + " " +
                    Comparison_Sky_DN[i].ToString("#########0.000000").PadLeft(20));
            }

            bool hasEmptyBins = false;

            /* Compute normal point times and luminosities */
            Time_Interval = (Time[Number_Obs - 1] - Time[0]) / (float)Normal_Points;
            for (i = 0; i < Normal_Points; i++)
            {
                Time_Start              = Time[0] + i * Time_Interval;
                Time_Normal[i]          = Time_Start + Time_Interval / 2.0;
                Time_Stop               = Time_Start + Time_Interval;
                Luminosity_Normal_Sum   = 0.0;
                Luminosity_Normal_Count = 0;
                for (j = 0; j < Number_Obs; j++)
                {
                    if ((Time[j] >= Time_Start) && (Time[j] < Time_Stop))
                    {
                        Luminosity_Normal_Sum   = Luminosity_Normal_Sum + Luminosity_Ratio[j];
                        Luminosity_Normal_Count = Luminosity_Normal_Count + 1;
                    }
                }

                if (Luminosity_Normal_Count > 0)
                {
                    Luminosity_Normal[i] = Luminosity_Normal_Sum / (float)Luminosity_Normal_Count;
                    rv.Normals_File.Add(Time_Normal[i].ToString("#########0.000000").PadLeft(20) + " " + Luminosity_Normal[i].ToString("#########0.000000").PadLeft(20));
                }
                else
                {
                    hasEmptyBins         = true;
                    Luminosity_Normal[i] = double.NaN;
                }
            }

            if (hasEmptyBins)
            {
                for (i = 0; i < Normal_Points; i++)
                {
                    bool isEmptyBin = double.IsNaN(Luminosity_Normal[i]);
                    if (isEmptyBin)
                    {
                        double?prevBin2  = i <= 1 ? (double?)null : Luminosity_Normal[i - 2];
                        double?prevBin   = i == 0 ? (double?)null : Luminosity_Normal[i - 1];
                        var    emptyBins = new List <double>();
                        long   k         = i;
                        while (k < Normal_Points && double.IsNaN(Luminosity_Normal[k]))
                        {
                            k++;
                            emptyBins.Add(double.NaN);
                        }
                        double?nextBin  = k == Normal_Points ? (double?)null : Luminosity_Normal[k];
                        double?nextBin2 = k + 1 < Normal_Points || k + 1 >= Luminosity_Normal.Length ? (double?)null : Luminosity_Normal[k + 1];

                        if ((prevBin == null && nextBin2 == null) || (prevBin2 == null && nextBin == null))
                        {
                            rv.ErrorMessage = "Too many empty bins!";
                            return(rv);
                        }

                        double step = 0;
                        if (prevBin == null)
                        {
                            step = nextBin2.Value - nextBin.Value;
                        }
                        else if (nextBin == null)
                        {
                            step = prevBin.Value - prevBin2.Value;
                        }
                        else
                        {
                            step = (nextBin.Value - prevBin.Value) / (1 + emptyBins.Count);
                        }


                        for (int l = 0; l < emptyBins.Count; l++)
                        {
                            Luminosity_Normal[i + l] = prevBin.Value + l * step;
                        }
                    }
                }
            }

            rv.Buckets.Clear();
            rv.Buckets.AddRange(Luminosity_Normal);

            /* Locate the faintest luminosity */
            Luminosity_Faintest       = 1000000000.0;
            Luminosity_Faintest_Index = 0;
            for (i = 0; i < Normal_Points; i++)
            {
                if (Luminosity_Normal[i] < Luminosity_Faintest)
                {
                    Luminosity_Faintest_Index = i;
                    Luminosity_Faintest       = Luminosity_Normal[i];
                }
            }

            /* Set the limits of the light curve to be symmetrical around the faintest luminosity */
            Start_Light_Curve   = 0;
            Stop_Light_Curve    = Normal_Points - 1;
            Normal_Point_Middle = Normal_Points / 2;
            if (Luminosity_Faintest_Index < Normal_Point_Middle)
            {
                Stop_Light_Curve = 2 * Luminosity_Faintest_Index;
            }
            if (Luminosity_Faintest_Index > Normal_Point_Middle)
            {
                Start_Light_Curve = 2 * Luminosity_Faintest_Index - Normal_Points + 1;
            }
            rv.IncludedObservations = 100 * (Stop_Light_Curve - Start_Light_Curve - 2) / BASE_NUMBER;

            rv.Start_Light_Curve = Start_Light_Curve;
            rv.Stop_Light_Curve  = Stop_Light_Curve;

            double startTime  = Time[0] + Start_Light_Curve * Time_Interval;
            double stopTime   = Time[0] + (Stop_Light_Curve + 1) * Time_Interval;
            long   startIndex = 0;
            long   stopIndex  = Number_Obs - 1;

            for (int k = 0; k < Number_Obs; k++)
            {
                if (Start_Light_Curve > 0 && Time[k] <= startTime)
                {
                    startIndex = k + 1;
                }
                if (Stop_Light_Curve < Number_Obs - 1 && k > 1 && Time[k] > stopTime && Time[k - 1] < stopTime)
                {
                    stopIndex = k - 1;
                }
            }
            rv.Start_Light_Curve_Obs_Index = startIndex;
            rv.Stop_Light_Curve_Obs_Index  = stopIndex;

            /* Compute the normalized sums of squares of luminosity differences across an array of times */
            Start_Sum_Squares = Start_Light_Curve + 1;
            Stop_Sum_Squares  = Stop_Light_Curve - 1;
            for (i = Start_Sum_Squares; i <= Stop_Sum_Squares; i++)
            {
                Sum_Of_Squares          = 0.0;
                Sum_Of_Squares_Count[i] = 0;

                for (j = 0; j < Normal_Points; j++)
                {
                    if (i - j >= 0 && i + j < Normal_Points)
                    {
                        Sum_Of_Squares          = Sum_Of_Squares + Math.Pow(Luminosity_Normal[i - j] - Luminosity_Normal[i + j], 2);
                        Sum_Of_Squares_Count[i] = Sum_Of_Squares_Count[i] + 1;
                    }
                }

                Sum_Of_Squares_Mean[i] = Sum_Of_Squares / (float)Sum_Of_Squares_Count[i];
            }

            rv.Sum_Of_Squares_Count.Clear();
            rv.Sum_Of_Squares_Count.AddRange(Sum_Of_Squares_Count);
            rv.Sum_Of_Squares_Mean.Clear();
            rv.Sum_Of_Squares_Mean.AddRange(Sum_Of_Squares_Mean);

            /* Find the smallest normalized sum of squares */
            Sum_Of_Squares_Smallest       = 1000000000;
            Sum_Of_Squares_Smallest_Index = 0;
            for (i = Start_Sum_Squares; i <= Stop_Sum_Squares; i++)
            {
                if (Sum_Of_Squares_Mean[i] < Sum_Of_Squares_Smallest)
                {
                    /* Must also have a reasonable sample of points */
                    if (Sum_Of_Squares_Count[i] > Normal_Points / 10)
                    {
                        Sum_Of_Squares_Smallest_Index = i;
                        Sum_Of_Squares_Smallest       = Sum_Of_Squares_Mean[i];
                    }
                }
            }

            rv.Sum_Of_Squares_Smallest_Index = Sum_Of_Squares_Smallest_Index;

            if (Sum_Of_Squares_Smallest_Index - 2 < 0 ||
                Sum_Of_Squares_Smallest_Index + 2 > Sum_Of_Squares_Mean.Length - 1)
            {
                rv.ErrorMessage = string.Format("Cannot locate the smallest normalized sum of squares (Index = {0})", Sum_Of_Squares_Smallest_Index);
                return(rv);
            }

            /* Solve the quadratic equation */
            for (i = 0; i <= 3; i++)
            {
                Quad[i] = Sum_Of_Squares_Mean[Sum_Of_Squares_Smallest_Index + i - 2];
            }

            A = -Quad[2] + (Quad[3] + Quad[1]) / 2.0;
            B = -3.0 * A + Quad[2] - Quad[1];
            C = Quad[1] - A - B;

            /* Calculate the time of minimum and uncertainty */
            T0             = -B / (2.0 * A);
            T0_Uncertainty = Math.Sqrt((4.0 * A * C - B * B) / (4.0 * A * A) / ((float)Normal_Points / 4.0 - 1.0));

            rv.T0                          = T0;
            rv.T0_Uncertainty              = T0_Uncertainty;
            rv.Time_Of_Minimum             = Time_Normal[1] + ((Sum_Of_Squares_Smallest_Index - 1) + (T0 - 2.0)) * Time_Interval;
            rv.Time_Of_Minimum_JD          = Time_First_JD + rv.Time_Of_Minimum;
            rv.Time_Of_Minimum_Uncertainty = T0_Uncertainty * Time_Interval;
            rv.Success                     = true;

            rv.Summary_File.Add(string.Format("      Time_First               Number_Obs"));
            rv.Summary_File.Add(Time_First_JD.ToString("#########0.000000").PadLeft(20) + " " + Number_Obs.ToString("#########0").PadLeft(20));
            rv.Summary_File.Add(string.Format("\n               Time of minimum: \n"));
            rv.Summary_File.Add(string.Format("      Bins-Quadratic          Uncertainty"));
            rv.Summary_File.Add(T0.ToString("#########0.000000").PadLeft(20) + " " + T0_Uncertainty.ToString("#########0.000000").PadLeft(20));
            rv.Summary_File.Add(string.Format("      From Time_First         Uncertainty"));
            rv.Summary_File.Add(rv.Time_Of_Minimum.ToString("#########0.000000").PadLeft(20) + " " + rv.Time_Of_Minimum_Uncertainty.ToString("#########0.000000").PadLeft(20));
            rv.Summary_File.Add(string.Format("      Absolute                Uncertainty"));
            rv.Summary_File.Add(rv.Time_Of_Minimum_JD.ToString("#########0.000000").PadLeft(20) + " " + rv.Time_Of_Minimum_Uncertainty.ToString("#########0.000000").PadLeft(20));

            /* Finish */
            return(rv);
        }