コード例 #1
0
 public async Task <Tuple <double, double> > AlphaFromRawData(List <RawLJVDatum> data)
 {
     return(await Task.Run(() =>
     {
         Tuple <double, double> alphaAndR2 = new Tuple <double, double>(-1, 0.001);
         List <double> pdBCData = new List <double>();
         List <double> camData = new List <double>();
         foreach (RawLJVDatum raw in data)
         {
             if (raw.CameraLuminance != null)
             {
                 //interpolate readings to account for device instability
                 pdBCData.Add(Convert.ToDouble((raw.PhotoCurrentB + raw.PhotoCurrentC)) / 2.0f);
                 camData.Add(Convert.ToDouble(raw.CameraLuminance));
             }
         }
         if (camData.Count > 2)
         {
             double[] xdata = pdBCData.ToArray();
             double[] ydata = camData.ToArray();
             Tuple <double, double> p = Fit.Line(xdata, ydata);
             Debug.WriteLine("Measured Alpha = " + p.Item2);
             double rsquared = GoodnessOfFit.RSquared(xdata.Select(x => p.Item1 + p.Item2 *x), ydata);
             alphaAndR2 = new Tuple <double, double>(p.Item2, rsquared);
             Debug.WriteLine("R^2 was: " + rsquared);
         }
         //take the ratio from a single measurement if not enough data for linear regression
         else if (camData.Count <= 2 && camData.Count >= 1)
         {
             double ratioAlpha = camData.Last() / pdBCData.Last();
             alphaAndR2 = new Tuple <double, double>(ratioAlpha, 0);
         }
         return alphaAndR2;
     }).ConfigureAwait(false));
 }
コード例 #2
0
ファイル: Strategy.cs プロジェクト: venyowong/Butler
        private static async Task <(double R2, double Beta)> RollingRegression(string fundCode, string index, DateTime end)
        {
            var fundExcessReturn = await GetFundExcessReturn(fundCode, end.AddDays(-13 * 7), end);

            if (!fundExcessReturn.Any())
            {
                return(double.NaN, 1);
            }

            var styleExcessReturn = GetStyleExcessReturn(index, end.AddDays(-13 * 7), end);
            var y = new List <double>();
            var x = new List <double>();

            foreach (var item in styleExcessReturn)
            {
                var fundItem = fundExcessReturn.FirstOrDefault(it => it.Begin == item.Begin);
                if (fundItem == null)
                {
                    continue;
                }

                y.Add((double)fundItem.ExcessReturn);
                x.Add((double)item.ExcessReturn);
            }
            if (x.Count < 2)
            {
                return(double.NaN, 1);
            }

            var fitResult = Fit.Line(x.ToArray(), y.ToArray());
            var y2        = x.Select(item => fitResult.Item1 + fitResult.Item2 * item).ToArray();

            return(GoodnessOfFit.RSquared(y2, y), fitResult.Item2);
        }
コード例 #3
0
        public double GetR2(List <EDFSample> samples)
        {
            if (samples.Count <= 1)
            {
                return(0);
            }
            double[] Time   = new double[samples.Count];
            double[] Amount = new double[samples.Count];

            int counter = 0;

            foreach (EDFSample item in samples)
            {
                Time[counter]   = int.Parse(item.DATE);
                Amount[counter] = double.Parse(item.RESULT);
                counter++;
            }
            Tuple <double, double> t = SimpleRegression.Fit(Time, Amount);
            double a = t.Item2;
            double b = t.Item1;

            double[] model = new double[Time.Length];
            for (int x = 0; x < Time.Count(); x++)
            {
                model[x] = (Time[x] * a) + b;
            }

            return(GoodnessOfFit.RSquared(model, Amount));
        }
コード例 #4
0
        private static void TestMath()
        {
            var observed = new double[] { 1, 2, 3, 4, 5 };
            var modelled = new double[] { 1.1, 2.1, 3.1, 4.1, 5.1 };

            var a = GoodnessOfFit.CoefficientOfDetermination(observed, modelled);
            var b = GoodnessOfFit.RSquared(observed, modelled);
        }
コード例 #5
0
 public IDataQualityReport <double> GetReport(IList <double> expected, IList <double> actual)
 {
     return(new RegressionQualityReport(
                expected,
                actual,
                expected.Count,
                GoodnessOfFit.RSquared(expected, actual),
                CalculateError(expected, actual)));
 }
コード例 #6
0
        CalculateRSquaredValue(IModelledFunction modelledFunction,
                               IEnumerable <double> observedValues)
        {
            double rSquaredValue = GoodnessOfFit.RSquared(
                observedValues, modelledFunction.Calculate(observedValues)
                );

            return(modelledFunction, rSquaredValue);
        }
コード例 #7
0
        public Vector2 Train(IList <GazeToDisplayCoordinateMappingRecord> data)
        {
            Samples = data.ToArray();

            var predict   = data.Select(r => Predict(new PoseAndEyeAndFace(r.HeadPose, r.Gaze, r.Face))).ToArray();
            var rSquaredX = GoodnessOfFit.RSquared(predict.Select(p => (double)p.X), data.Select(d => d.Display.X).Select(d => (double)d));
            var rSquaredY = GoodnessOfFit.RSquared(predict.Select(p => (double)p.Y), data.Select(d => d.Display.Y).Select(d => (double)d));

            return(new Vector2((float)rSquaredX, (float)rSquaredY));
        }
コード例 #8
0
        public (double RSquaredX, double RSquaredY) Train(IList <Record> data)
        {
            Samples = data.ToArray();

            var predict   = data.Select(r => Predict(new HeadPoseAndGaze(r.HeadPose, r.Gaze))).ToArray();
            var rSquaredX = GoodnessOfFit.RSquared(predict.Select(p => p.CoordinateX), data.Select(d => d.Display.X));
            var rSquaredY = GoodnessOfFit.RSquared(predict.Select(p => p.CoordinateY), data.Select(d => d.Display.Y));

            return(rSquaredX, rSquaredY);
        }
コード例 #9
0
        internal static (double b0, double b1, double r2) LinealRegression(int[] xdata, int[] ydata)
        {
            var x = xdata.Select(c => (double)c).ToArray();
            var y = ydata.Select(c => (double)c).ToArray();
            Tuple <double, double> p = Fit.Line(x, y);
            double a  = Math.Round(p.Item1, 5);
            double b  = Math.Round(p.Item2, 5);
            var    r2 = GoodnessOfFit.RSquared(xdata.Select(x => a + b * x), y);

            return(a, b, Math.Round(r2, 4));
        }
コード例 #10
0
        public static SKUPrediction GenerateSkuPreduction(SKU sku, DateTime PredictionDate)
        {
            int Id = sku.Id;

            double[] YValues                = sku.MonthlyTotals.ToArray();
            double[] NormalizedYs           = RemoveSeasonality(sku.Months.Select(o => o.Month).ToArray(), YValues);
            double[] ScalarDates            = sku.Months.Select(o => o.ToOADate()).ToArray();
            Tuple <double, double> p        = Fit.Line(ScalarDates, NormalizedYs);
            double Slope                    = p.Item2;
            double Intercept                = p.Item1;
            double PredictedTotal           = Slope * PredictionDate.ToOADate() + Intercept;
            double SeasonallyPredictedTotal = AddSeasonality(PredictionDate.Month, PredictedTotal);
            int    SeasonallyPredictedTotalRounded;

            if (Slope > 0)
            {
                SeasonallyPredictedTotalRounded = (int)Math.Ceiling(SeasonallyPredictedTotal);
            }
            else
            {
                SeasonallyPredictedTotalRounded = (int)Math.Floor(SeasonallyPredictedTotal);
            }

            string SkuClass = GetSkuClass(sku.MonthlyTotals.ToArray());

            double GoodnessOfFitVar = GoodnessOfFit.RSquared(ScalarDates.Select(x => Intercept + Slope * x), NormalizedYs); // == 1.0

            double StdDev = Statistics.PopulationStandardDeviation(YValues);

            double Zscore = (SeasonallyPredictedTotalRounded - YValues.Average()) / StdDev;

            return(new SKUPrediction()
            {
                Id = Id,
                GoodnessOfFitRSquare = GoodnessOfFitVar,
                Intercept = Intercept,
                PredictedTotal = PredictedTotal,
                PredictionDate = PredictionDate,
                SeasonallyPredictedTotal = SeasonallyPredictedTotal,
                SeasonallyPredictedTotalRounded = SeasonallyPredictedTotalRounded,
                SkuClass = SkuClass,
                Slope = Slope,
                StandardDeviation = StdDev,
                ZScore = Zscore
            });
        }
コード例 #11
0
        public void testRegression()
        {
            Console.WriteLine("---------------------------");
            var ans = Fit.Line(X, Y);
            var a   = ans.Item1;
            var b   = ans.Item2;

            Console.WriteLine("intercept:{0}, slope:{1}", ans.Item1, ans.Item2);
            Console.WriteLine("r^2:" + GoodnessOfFit.RSquared(X.Select(x => a + b * x), Y));

            Console.WriteLine("-------------------------");
            var p = Fit.Polynomial(X, Y, 3);

            Console.WriteLine("p:" + string.Join(",", p));
            Console.WriteLine("r^2:" + GoodnessOfFit.RSquared(X.Select(x => p[0] + p[1] * x + p[2] * x * x + p[3] * x * x * x), Y));
            Assert.True(true);
        }
コード例 #12
0
        /// <summary>
        /// Polynominal 커브피팅
        /// </summary>
        /// <param name="x">x축 값 배열</param>
        /// <param name="y">y축 값 배열</param>
        /// <param name="order">커브피팅하고자 하는 다항식 차수</param>
        /// <returns></returns>
        //다항 커브피팅 6차 다항식까지 지원
        public static double[] polynominalRegression(double[] x, double[] y, int order) // x: x 배열, y: y: 배열, order :차수
        {
            double[] p  = Fit.Polynomial(x, y, order);                                  //curve fitting 하여 반환
            double   R2 = 0;

            switch (order)
            {
            case 2:
                R2 = GoodnessOfFit.RSquared(x.Select(d => p[0] + p[1] * d + p[2] * Math.Pow(d, 2)), y);
                break;

            case 3:
                R2 = GoodnessOfFit.RSquared(x.Select(d => p[0] + p[1] * d + p[2] * Math.Pow(d, 2) + p[3] * Math.Pow(d, 3)), y);
                break;

            case 4:
                R2 = GoodnessOfFit.RSquared(x.Select(d => p[0] + p[1] * d + p[2] * Math.Pow(d, 2) + p[3] * Math.Pow(d, 3) + p[4] * Math.Pow(d, 4)), y);
                break;

            case 5:
                R2 = GoodnessOfFit.RSquared(x.Select(d => p[0] + p[1] * d + p[2] * Math.Pow(d, 2) + p[3] * Math.Pow(d, 3) + p[4] * Math.Pow(d, 4) + p[5] * Math.Pow(d, 5)), y);
                break;

            case 6:
                R2 = GoodnessOfFit.RSquared(x.Select(d => p[0] + p[1] * d + p[2] * Math.Pow(d, 2) + p[3] * Math.Pow(d, 3) + p[4] * Math.Pow(d, 4) + p[5] * Math.Pow(d, 5) + p[6] * Math.Pow(d, 6)), y);
                break;

            case 7:
                R2 = GoodnessOfFit.RSquared(x.Select(d => p[0] + p[1] * d + p[2] * Math.Pow(d, 2) + p[3] * Math.Pow(d, 3) + p[4] * Math.Pow(d, 4) + p[5] * Math.Pow(d, 5) + p[6] * Math.Pow(d, 6)), y);
                break;

            case 8:
                R2 = GoodnessOfFit.RSquared(x.Select(d => p[0] + p[1] * d + p[2] * Math.Pow(d, 2) + p[3] * Math.Pow(d, 3) + p[4] * Math.Pow(d, 4) + p[5] * Math.Pow(d, 5) + p[6] * Math.Pow(d, 6)), y);
                break;
            }

            double[] result = new double[order + 2];
            result[0] = R2;

            for (var i = 0; i <= order; i++)
            {
                result[i + 1] = p[i];
            }

            return(result);
        }
コード例 #13
0
        List <double> UpdateLinRegEquation(double[] KG, double[] MV)
        {
            List <double> linregTemp = new List <double>();

            if (KG.Count() > 2)
            {
                double[] p    = Fit.Polynomial(MV, KG, 1);
                double   rSqr = GoodnessOfFit.RSquared(MV.Select(x => p[1] * x + p[0]), KG);
                linregTemp.Add(p[1]);
                linregTemp.Add(p[0]);
                linregTemp.Add(rSqr);
                this.BeginInvoke(new Action(() =>
                {
                    if (tipoSelected == "1D - 500x500")
                    {
                        EquationBox.Text = "Fy: " + Math.Round(linregTemp[0], 5) + "x + (" + Math.Round(linregTemp[1], 5) + ") [Kg] --> " + "R2: " + Math.Round(linregTemp[2], 5);
                    }
                    //EquationBox.Text = "Fy: " + Math.Round(SLOPE, 5) + "x + (" + Math.Round(INTERCEPT, 5) + ") [Kg] --> " + "R2: " + Math.Round(RSQR, 5);
                    else if (tipoSelected == "3D - 500x500")
                    {
                        if (FyCheckBox.Checked)
                        {
                            EquationBox.Text = "Fy: " + Math.Round(linregTemp[0], 5) + "x + (" + Math.Round(linregTemp[1], 5) + ") [Kg] --> " + "R2: " + Math.Round(linregTemp[2], 5);
                        }
                        if (MxCheckBox.Checked)
                        {
                            EquationBox.Text = "Mx: " + Math.Round(linregTemp[0], 5) + "x + (" + Math.Round(linregTemp[1], 5) + ") [Kg] --> " + "R2: " + Math.Round(linregTemp[2], 5);
                        }
                        if (MzCheckBox.Checked)
                        {
                            EquationBox.Text = "Mz: " + Math.Round(linregTemp[0], 5) + "x + (" + Math.Round(linregTemp[1], 5) + ") [Kg] --> " + "R2: " + Math.Round(linregTemp[2], 5);
                        }
                    }
                }));
            }
            else
            {
                this.BeginInvoke(new Action(() =>
                {
                    EquationBox.Text = "São necessários pelo menos 3 medidas.";
                }));
            }
            return(linregTemp);
        }
コード例 #14
0
        public static double[] powerRegression(double[] x, double[] y)
        {
            var convert_log = y.Select(d => Math.Log(d)).ToArray();

            double[] p = Fit.LinearCombination(x, convert_log,
                                               d => 1.0,
                                               d => Math.Log(d)
                                               );

            p[0] = Math.Exp(p[0]);

            var R2 = GoodnessOfFit.RSquared(x.Select(d => p[0] * Math.Pow(d, p[1])), y);

            double[] result = new double[3];
            result[0] = R2;
            result[1] = p[0];
            result[2] = p[1];

            return(result);
        }
コード例 #15
0
        void LinRegRaw()
        {
            try
            {
                LinRegChart.Series.Clear();
                LinRegChart.ChartAreas[0].CursorX.IsUserEnabled          = false;
                LinRegChart.ChartAreas[0].CursorY.IsUserEnabled          = false;
                LinRegChart.ChartAreas[0].AxisX.ScaleView.Zoomable       = false;
                LinRegChart.ChartAreas[0].AxisY.ScaleView.Zoomable       = false;
                LinRegChart.ChartAreas[0].CursorX.AutoScroll             = false;
                LinRegChart.ChartAreas[0].CursorY.AutoScroll             = false;
                LinRegChart.ChartAreas[0].CursorX.IsUserSelectionEnabled = false;
                LinRegChart.ChartAreas[0].CursorY.IsUserSelectionEnabled = false;

                double[] KGinit = { 0, 10, 20, 30, 40, 50, 60 };
                double[] MVinit = { 0, 5, 10, 15, 20, 25, 30 };
                double[] p      = Fit.Polynomial(MVinit, KGinit, 2);
                double   rSqr   = GoodnessOfFit.RSquared(MVinit.Select(x => p[1] * x + p[2]), KGinit);
                EquationBox.Text = "Fy: " + Math.Round(p[1], 5) + "x + (" + Math.Round(p[2], 5) + ") [Kg] --> " + "R2: " + Math.Round(rSqr, 5);

                Series s = new Series();
                for (int i = 0; i < KGinit.Count(); i++)
                {
                    s.Points.AddXY(KGinit[i], MVinit[i]);
                }
                LinRegChart.Series.Add(s);
                LinRegChart.Series[0].ChartType       = SeriesChartType.Point;
                LinRegChart.Series[0].Color           = Color.Blue;
                LinRegChart.Series[0].BorderWidth     = 3;
                LinRegChart.ChartAreas[0].AxisX.Title = "Carga Vertical (KG)";
                LinRegChart.ChartAreas[0].AxisY.Title = "Tensão (mV)";

                LinRegChart.ChartAreas[0].AxisX.Maximum  = 60;
                LinRegChart.ChartAreas[0].AxisX.Minimum  = 0;
                LinRegChart.ChartAreas[0].AxisX.Interval = 10;
                LinRegChart.ChartAreas[0].AxisY.Maximum  = 30;
                LinRegChart.ChartAreas[0].AxisY.Minimum  = 0;
                LinRegChart.ChartAreas[0].AxisY.Interval = 5;
            }
            catch (Exception ex) { MessageBox.Show("Erro: " + ex.Message); }
        }
コード例 #16
0
        /// <summary>
        /// Get the regression parameter (slope, interception and r).
        /// </summary>
        /// <param name="xData">X data.</param>
        /// <param name="yData">Y data.</param>
        /// <returns>A DTOLineFitParameters object containing the regression parameters.</returns>
        public DTOLineFitParameters getRegressionParameters(double[] xData, double[] yData)
        {
            if (xData.Count() < 2 || yData.Count() < 2)
            {
                return(new DTOLineFitParameters());
            }
            // Fit the data to a line
            Tuple <double, double> p = Fit.Line(xData, yData);

            // Get parameters
            var slope        = p.Item2;
            var interception = p.Item1;
            var ret          = new DTOLineFitParameters
            {
                Slope        = slope,
                Interception = interception,
                R            = GoodnessOfFit.RSquared(xData.Select(x => slope + interception * x), yData)
            };

            return(ret);
        }
コード例 #17
0
        public void FindLowestIndexReverse(List <ChartData> data)
        {
            // Find the lowest value in the list
            int storeIndex = data.Count - 1;
            int storedata  = data[storeIndex].Value;

            for (int i = data.Count - 2; i >= 0; i--)
            {
                if (storedata > data[i].Value)
                {
                    storeIndex = i;
                    storedata  = data[i].Value;
                }
                else
                {
                    break;
                }
            }

            // Convert the list from the lowest value index to the last value
            // to a array of double
            List <double> xlist = new List <double>();
            List <double> ylist = new List <double>();

            for (int i = storeIndex; i < data.Count; i++)
            {
                xlist.Add(i - storeIndex);
                ylist.Add(Convert.ToDouble(data[i].Value));
            }

            xdata = xlist.ToArray <double>();
            ydata = ylist.ToArray <double>();

            // Linear regression
            if (xdata.Count() >= 2 && ydata.Count() >= 2)
            {
                f           = Fit.Line(xdata, ydata);
                goodnessFit = GoodnessOfFit.RSquared(xdata.Select(x => f.Item1 + f.Item2 * x), ydata); // == 1.0
            }
        }
コード例 #18
0
        public bool Exists()
        {
            try
            {
                //normalize
                var curve = _spectrum.SpectrumData.Where(p => p.X >= 560 && p.X <= 740).ToList();
                var x     = curve.Select(p => p.X).ToArray();
                var y     = curve.Select(p => p.Y).ToArray();
                var minY  = y.Min();
                var maxY  = y.Max();
                y     = y.Select(p => (p - minY) / (maxY - minY)).ToArray();
                curve = x.Zip(y, (xp, yp) => new System.Windows.Point(xp, yp)).ToList();

                //fit linear function
                var curve1        = curve.Where(p => p.X >= 650 && p.X <= 740).ToList();
                var xData         = curve1.Select(p => p.X).ToArray();
                var yData         = curve1.Select(p => p.Y).ToArray();
                var linear        = Fit.Line(xData, yData);
                var intercept     = linear.Item1;
                var slope         = linear.Item2;
                var goodnessOfFit = GoodnessOfFit.RSquared(xData.Select(d => slope * d + intercept), yData);

                bool rule1 = (slope > 0.004) && (goodnessOfFit > 0.95);
                if (!rule1)
                {
                    return(false);
                }



                return(true);
            }
            catch
            {
            }

            return(true);
        }
コード例 #19
0
        static async Task Main(string[] args)
        {
            var savegameFile = args.FirstOrDefault();

            if (savegameFile == null)
            {
                Console.Error.WriteLine("Usage: MapCalibrator.exe <savegame>");
                Environment.Exit(1);
            }

            var arkDataFile = Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Larkator"), "ark-data.json");
            var arkData     = ArkDataReader.ReadFromFile(arkDataFile);

            (GameObjectContainer gameObjects, float gameTime) = await ReadSavegameFile(savegameFile);

            // Find any objects that have a relevant BoxName
            var items = gameObjects
                        .Where(o => o.Parent == null && o.GetPropertyValue <string>("BoxName", defaultValue: "").StartsWith("Calibration:"))
                        .ToList();

            // Extract XYZ location and calibration lat/lon
            var inputs = items.Select(o => (o.Location, LatLon: LatLongFromName(o.GetPropertyValue <string>("BoxName")))).ToArray();

            // Perform linear regression on the values for best fit, separately for X and Y
            double[] xValues   = inputs.Select(i => (double)i.Location.X).ToArray();
            double[] yValues   = inputs.Select(i => (double)i.Location.Y).ToArray();
            double[] lonValues = inputs.Select(i => i.LatLon.Lon).ToArray();
            double[] latValues = inputs.Select(i => i.LatLon.Lat).ToArray();
            var(xOffset, xMult) = Fit.Line(xValues, lonValues);
            var(yOffset, yMult) = Fit.Line(yValues, latValues);
            var xCorr = GoodnessOfFit.RSquared(xValues.Select(x => xOffset + xMult * x), lonValues);
            var yCorr = GoodnessOfFit.RSquared(yValues.Select(y => yOffset + yMult * y), latValues);

            Console.WriteLine($"X: {xOffset} + X/{1 / xMult}  (corr {xCorr})");
            Console.WriteLine($"Y: {yOffset} + X/{1 / yMult}  (corr {yCorr})");

            Console.ReadLine();
        }
コード例 #20
0
        public void LineFit(Tuple <List <double>, List <double> > edgeSegment, List <Tuple <double, double> > linesOfAnEdgeSegment)
        {
            List <double> xData = new List <double>();

            xData = edgeSegment.Item1;
            List <double> yData = new List <double>();

            yData = edgeSegment.Item2;



            double lineFitError   = Double.MaxValue;
            int    numberOfPixels = xData.Count;

            lineFitError = Double.MaxValue; // current line fit error

            Tuple <double, double> line;    // y = ax+b OR x = ay+b
            double a = 0;
            double b = 0;

            while (numberOfPixels > MIN_LINE_LENGTH)
            {
                Tuple <double, double> line2 = Fit.Line(xData.ToArray(), yData.ToArray());

                a = line2.Item1;
                b = line2.Item2;
                GoodnessOfFit.RSquared(xData.Select(x => a + b * x), yData.ToArray());
                if (lineFitError <= 1.0)
                {
                    break; // OK. An initial line segment detected
                }
                // Skip the first pixel & try with the remaining pixels
                xData.RemoveAt(xData.Count - 1);
                yData.RemoveAt(yData.Count - 1);

                numberOfPixels--; // One less pixel
            } // end-while



            if (lineFitError > 1.0)
            {
                return; // no initial line segment. Done.
            }
            // An initial line segment detected. Try to extend this line segment

            int           lineLen       = MIN_LINE_LENGTH;
            List <double> xDataExtended = new List <double>();
            List <double> yDataExtended = new List <double>();

            for (int i = 0; i < MIN_LINE_LENGTH; i++)
            {
                xDataExtended[i] = xData[i];
                yDataExtended[i] = yData[i];
            }

            while (lineLen < numberOfPixels)
            {
                double x = edgeSegment.Item1[lineLen];
                double y = edgeSegment.Item2[lineLen];


                double d = ComputePointDistance2Line(a, -1, b, (int)x, (int)y);

                if (d > 1.0)
                {
                    break;
                }

                lineLen++;
            } //end-while



            // End of the current line segment. Compute the final line equation & output it.

            Tuple <double, double> line3 = Fit.Line(xDataExtended.ToArray(), yDataExtended.ToArray());

            linesOfAnEdgeSegment.Add(line3);



            // Extract line segments from the remaining pixels
            for (int i = lineLen; i < edgeSegment.Item1.Count; i++)
            {
                xData[i - lineLen] = edgeSegment.Item1[i];
                yData[i - lineLen] = edgeSegment.Item2[i];
            }
            for (int i = 0; i < lineLen; i++)
            {
                edgeSegment.Item1.RemoveAt(i);
                edgeSegment.Item2.RemoveAt(i);
            }
            LineFit(edgeSegment);
        }
コード例 #21
0
        public static MetalTemperatureClass MultiMetalTemperatureCaculate(List <PValue> valueList, double LimitHH, double LimitH, double LimitRP, double LimitOO, double LimitRN, double LimitL, double LimitLL)
        {
            try
            {
                List <MetalTemperatureClass> returnClass = new List <MetalTemperatureClass>();

                MetalTemperatureClass newClass = new MetalTemperatureClass();
                int l = 1;
                List <CurveClass> ccList = new List <CurveClass>();
                foreach (PValue childItem in valueList)
                {
                    CurveClass cc = new CurveClass();
                    cc.x = l;
                    cc.y = childItem.Value;
                    ccList.Add(cc);
                    l++;
                }
                double Min     = ccList[0].y;
                double MinN    = 1;
                double Max     = ccList[0].y;
                double MaxN    = 1;
                double Sum     = 0;
                double HHG     = 0;
                double HHHB    = 0;
                double HRPB    = 0;
                double RP0B    = 0;
                double RM0B    = 0;
                double RMLB    = 0;
                double LLLB    = 0;
                double LLL     = 0;
                double RPRMB   = 0;
                double HLB     = 0;
                double HHHLLLB = 0;
                double HHLLGL  = 0;
                double HG      = 0;
                double LL      = 0;

                foreach (CurveClass childItem in ccList)
                {
                    if (Min > childItem.y)
                    {
                        Min  = childItem.y;
                        MinN = childItem.x;
                    }
                    if (Max < childItem.y)
                    {
                        Max  = childItem.y;
                        MaxN = childItem.x;
                    }
                    Sum += childItem.y;

                    if (childItem.y > LimitHH)
                    {
                        HHG++;
                    }
                    if (childItem.y > LimitH)
                    {
                        HG++;
                    }
                    if (childItem.y <= LimitHH && childItem.y > LimitH)
                    {
                        HHHB++;
                    }
                    if (childItem.y <= LimitH && childItem.y > LimitRP)
                    {
                        HRPB++;
                    }
                    if (childItem.y <= LimitRP && childItem.y > LimitOO)
                    {
                        RP0B++;
                    }
                    if (childItem.y <= LimitOO && childItem.y > LimitRN)
                    {
                        RM0B++;
                    }
                    if (childItem.y <= LimitRN && childItem.y > LimitL)
                    {
                        RMLB++;
                    }
                    if (childItem.y <= LimitL && childItem.y > LimitLL)
                    {
                        LLLB++;
                    }
                    if (childItem.y <= LimitL)
                    {
                        LL++;
                    }
                    if (childItem.y <= LimitLL)
                    {
                        LLL++;
                    }
                }
                RPRMB         = RP0B + RM0B;
                HLB           = HRPB + RP0B + RM0B + RMLB;
                HHHLLLB       = HHHB + LLLB;
                HHLLGL        = HHG + LLL;
                newClass.Min  = Min.ToString();
                newClass.MinN = MinN.ToString();
                newClass.Max  = Max.ToString();
                newClass.MaxN = MaxN.ToString();
                double Avg = Math.Round(Sum / (double)(ccList.Count), 3);
                newClass.Avg = Avg.ToString();
                double xi   = Math.Abs(Avg - ccList[0].y);
                double AvgN = 1;

                double[] xList = new double[ccList.Count];
                double[] yList = new double[ccList.Count];
                int      n     = 0;
                foreach (CurveClass childItem in ccList)
                {
                    xList[n] = childItem.x;
                    yList[n] = childItem.y;
                    if (xi > Math.Abs(Avg - childItem.y))
                    {
                        xi   = Math.Abs(Avg - childItem.y);
                        AvgN = childItem.x;
                    }
                    n++;
                }
                double dMaxB  = ccList[1].y - ccList[0].y;
                double dMaxBN = 1;
                for (int i = 1; i < ccList.Count - 1; i++)
                {
                    if (dMaxB < ccList[i].y - ccList[i - 1].y)
                    {
                        dMaxB  = ccList[i].y - ccList[i - 1].y;
                        dMaxBN = ccList[i - 1].x;
                    }
                }
                newClass.AvgN   = AvgN.ToString();
                newClass.dX     = (Max - Min).ToString();
                newClass.dXNR   = Math.Round((MaxN - MinN) / (double)(ccList.Count), 3).ToString();
                newClass.dMaxB  = AvgN.ToString();
                newClass.dMaxBN = AvgN.ToString();
                newClass.sigma  = AlgorithmHelper.StandardDeviationSolve(ccList).ToString();
                double lk = 0;
                double lb = 0;
                AlgorithmHelper.LinearRegressionSolve(ccList, ref lk, ref lb);
                newClass.lk = lk.ToString();
                newClass.lb = lb.ToString();
                List <double> lY = new List <double>();
                List <double> lX = new List <double>();
                foreach (CurveClass lcItem in ccList)
                {
                    lY.Add(lcItem.y);
                    lX.Add(lcItem.x);
                }
                List <double> lYTest = new List <double>();
                foreach (double fdItem in lX)
                {
                    lYTest.Add(lk * fdItem + lb);
                }
                double lR = GoodnessOfFit.RSquared(lY, lYTest);
                newClass.lr = lR.ToString();
                double[] res = Fit.Polynomial(xList, yList, 2);
                newClass.qa = Math.Round(res[2], 3).ToString();
                newClass.qb = Math.Round(res[1], 3).ToString();
                newClass.qc = Math.Round(res[0], 3).ToString();
                List <double> qYTest = new List <double>();
                foreach (double qdItem in xList)
                {
                    qYTest.Add(res[2] * Math.Pow(qdItem, 2) + res[1] * qdItem + res[0]);
                }
                double qR = GoodnessOfFit.RSquared(yList, qYTest);
                newClass.qr = qR.ToString();
                double Bulge  = (ccList[1].y - ccList[0].y) * 2;
                double BulgeN = 1;
                double Cave   = (ccList[1].y - ccList[0].y) * 2;
                double CaveN  = 1;
                for (int i = 1; i < ccList.Count - 1; i++)
                {
                    double b = 0;
                    if (i == ccList.Count - 1)
                    {
                        b = (ccList[i].y - ccList[i - 1].y) * 2;
                    }
                    else
                    {
                        b = ccList[i].y * 2 - ccList[i - 1].y - ccList[i + 1].y;
                    }
                    if (Bulge < b)
                    {
                        Bulge  = b;
                        BulgeN = ccList[i].x;
                    }
                    if (Cave > b)
                    {
                        Cave  = b;
                        CaveN = ccList[i].x;
                    }
                }
                newClass.Bulge   = Bulge.ToString();
                newClass.BulgeN  = BulgeN.ToString();
                newClass.Cave    = Cave.ToString();
                newClass.CaveN   = CaveN.ToString();
                newClass.HHG     = Math.Round(HHG / (double)(ccList.Count), 3).ToString();
                newClass.HHHB    = Math.Round(HHHB / (double)(ccList.Count), 3).ToString();
                newClass.HRPB    = Math.Round(HRPB / (double)(ccList.Count), 3).ToString();
                newClass.RP0B    = Math.Round(RP0B / (double)(ccList.Count), 3).ToString();
                newClass.RM0B    = Math.Round(RM0B / (double)(ccList.Count), 3).ToString();
                newClass.RMLB    = Math.Round(RMLB / (double)(ccList.Count), 3).ToString();
                newClass.LLLB    = Math.Round(LLLB / (double)(ccList.Count), 3).ToString();
                newClass.LLL     = Math.Round(LLL / (double)(ccList.Count), 3).ToString();
                newClass.RPRMB   = Math.Round(RPRMB / (double)(ccList.Count), 3).ToString();
                newClass.HLB     = Math.Round(HLB / (double)(ccList.Count), 3).ToString();
                newClass.HHHLLLB = Math.Round(HHHLLLB / (double)(ccList.Count), 3).ToString();
                newClass.HHLLGL  = Math.Round(HHLLGL / (double)(ccList.Count), 3).ToString();
                newClass.HG      = Math.Round(HG / (double)(ccList.Count), 3).ToString();
                newClass.LL      = Math.Round(LL / (double)(ccList.Count), 3).ToString();
                //returnClass.Add(newClass);

                return(newClass);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
コード例 #22
0
 public void PopulatePropertiesFromPath(string fp)
 {
     TheELSpectrum.FilePath = fp;
     try
     {
         Debug.WriteLine("ELSpec filepath: " + fp);
         //perform linear fits on both sides of the gaussian to approximate where the peak would be if the spectrophotometer had better resolution
         LoadELSpecDataIntoList(fp);
         var max          = _ELSpecList.Max(x => x.Intensity);
         var maxListIndex = _ELSpecList.FindIndex(x => x.Intensity == max);
         Debug.WriteLine("Maximum ELSpec raw value is: " + max + " at list index: " + maxListIndex);
         foreach (ELSpecDatum e in _ELSpecList)
         {
             e.Intensity = e.Intensity / max;
         }
         //find points between 0.42 and 0.9 on the high energy side of the peak and add to list
         var leftList = new List <ELSpecDatum>();
         for (int i = 0; i < maxListIndex; i++)
         {
             if (_ELSpecList[i].Intensity > 0.42 && _ELSpecList[i].Intensity < 0.9)
             {
                 leftList.Add(_ELSpecList[i]);
             }
         }
         //same for lower energy side but in reverse
         var rightList = new List <ELSpecDatum>();
         for (int i = _ELSpecList.Count() - 1; i > maxListIndex; i--)
         {
             if (_ELSpecList[i].Intensity > 0.42 && _ELSpecList[i].Intensity < 0.9)
             {
                 rightList.Add(_ELSpecList[i]);
             }
         }
         if (leftList.Count >= 2 && rightList.Count >= 2)
         {
             //perform linear fits on these data
             double[] leftXData = leftList.Select(x => x.Wavelength).ToArray();
             double[] leftYData = leftList.Select(x => x.Intensity).ToArray();
             Tuple <double, double> leftVals = Fit.Line(leftXData, leftYData);
             //Debug.WriteLine("Left side line: Intensity = " + leftVals.Item2 + "x + " + leftVals.Item1);
             double rsquared = GoodnessOfFit.RSquared(leftXData.Select(x => leftVals.Item1 + leftVals.Item2 * x), leftYData);
             //Debug.WriteLine("R^2 = " + rsquared);
             double[] rightXData = rightList.Select(x => x.Wavelength).ToArray();
             double[] rightYData = rightList.Select(x => x.Intensity).ToArray();
             Tuple <double, double> rightVals = Fit.Line(rightXData, rightYData);
             //Debug.WriteLine("Right side line: Intensity = " + rightVals.Item2 + "x + " + rightVals.Item1);
             rsquared = GoodnessOfFit.RSquared(rightXData.Select(x => rightVals.Item1 + rightVals.Item2 * x), rightYData);
             //Debug.WriteLine("R^2 = " + rsquared);
             double calculatedPeakLambda = (leftVals.Item1 - rightVals.Item1) / (rightVals.Item2 - leftVals.Item2);
             //Debug.WriteLine("Calculated peak lambda to be: " + calculatedPeakLambda + "nm");
             TheELSpectrum.ELPeakLambda = Math.Round(Convert.ToDecimal(calculatedPeakLambda), 1);
             double leftLambdaAtHalfMax  = (0.5 - leftVals.Item1) / leftVals.Item2;
             double rightLambdaAtHalfMax = (0.5 - rightVals.Item1) / rightVals.Item2;
             var    calculatedFWHM       = Math.Round(Convert.ToDecimal(rightLambdaAtHalfMax - leftLambdaAtHalfMax), 1);
             //Debug.WriteLine("Calculated FWHM to be: " + calculatedFWHM + "nm");
             TheELSpectrum.ELFWHM = calculatedFWHM;
         }
         else
         {
             TheELSpectrum.ELPeakLambda = Convert.ToDecimal(_ELSpecList[maxListIndex].Wavelength);
             //need to update ELSpectrum entity with nullables
         }
         var CIEcoords = CIE1931Calculator.CalculateCIE1931CoordsFromFilePath(fp);
         TheELSpectrum.CIEx = Convert.ToDecimal(CIEcoords.Item1);
         TheELSpectrum.CIEy = Convert.ToDecimal(CIEcoords.Item2);
     }
     catch (Exception e)
     {
         Debug.WriteLine(e);
         MessageBox.Show(e.ToString());
     }
 }
コード例 #23
0
        //this is asych for the calling Task.WhenAll
        //but does not necessarily need internal asych awaits
        public async Task RunAlgorithmAsync(List <List <double> > data)
        {
            try
            {
                //minimal data requirement is first five cols
                if (_colNames.Count() < 5 ||
                    _mathTerms.Count() == 0)
                {
                    ErrorMessage = "Regression requires at least one dependent variable and one independent variable.";
                    return;
                }
                if (data.Count() < 5)
                {
                    //185 same as other analysis
                    ErrorMessage = "Regression requires at least 2 rows of observed data and 3 rows of scoring data.";
                    return;
                }
                //convert data to a Math.Net Matrix
                //v185 uses same ci technique as algos 2,3 and 4 -last 3 rows are used to generate ci
                List <List <double> > dataci = data.Skip(data.Count - _scoreRows).ToList();
                data.Reverse();
                List <List <double> > dataobs = data.Skip(_scoreRows).ToList();
                dataobs.Reverse();
                //actual observed values
                Vector <double> y  = Shared.GetYData(dataobs);
                Matrix <double> x  = Shared.GetDoubleMatrix(dataobs, _colNames, _depColNames);
                Matrix <double> ci = Shared.GetDoubleMatrix(dataci, _colNames, _depColNames);

                //model expected values - get the coefficents
                //use normal equations regression
                Vector <double> p = MultipleRegression.NormalEquations(x, y);
                //but note that this runs without errors in more cases but still does not give good results
                //Vector<double> p = MultipleRegression.QR(x, y);

                if (p.Count() != ci.Row(_scoreRows - 1).Count())
                {
                    //185 same as other analysis
                    ErrorMessage = "The scoring and training datasets have different numbers of columns.";
                    return;
                }
                //get the predicted yhats
                Vector <double> yhat = GetYHatandSetQTPred(y.Count, x, p, ci.Row(_scoreRows - 1).ToArray());
                //get the durbin-watson d statistic
                double d   = GetDurbinWatson(y, yhat);
                double SSE = 0;
                //sum of the square of the error (between the predicted, p, and observed, y);
                SSE = Distance.SSD(yhat, y);
                double rSquared = GoodnessOfFit.RSquared(yhat, y);
                //sum of the square of the regression (between the predicted, p, and observed mean, statsY.Mean);
                double SSR = 0;
                for (int i = 0; i < yhat.Count(); i++)
                {
                    SSR += Math.Pow((yhat[i] - y.Mean()), 2);
                }
                //set joint vars properties
                //degrees freedom
                double dfR         = x.ColumnCount - 1;
                double dfE         = x.RowCount - x.ColumnCount;
                int    idfR        = x.ColumnCount - 1;
                int    idfE        = x.RowCount - x.ColumnCount;
                double s2          = SSE / dfE;
                double s           = Math.Sqrt(s2);
                double MSR         = SSR / dfR;
                double MSE         = SSE / dfE;
                double FValue      = MSR / MSE;
                double adjRSquared = 1 - ((x.RowCount - 1) * (MSE / (SSE + SSR)));
                double pValue      = Shared.GetPValueForFDist(idfR, idfE, FValue);

                //correct 2 tailed t test
                //double TCritialValue = ExcelFunctions.TInv(0.05, idfE);
                //so do this
                double dbCI           = CalculatorHelpers.GetConfidenceIntervalProb(_confidenceInt);
                double tCriticalValue = ExcelFunctions.TInv(dbCI, idfE);
                //set each coeff properties
                //coeffs st error
                //use matrix math to get the standard error of coefficients
                Matrix <double> xt = x.Transpose();
                //matrix x'x
                Matrix <double> xx       = xt.Multiply(x);
                Matrix <double> xxminus1 = xx.Inverse();

                double   sxx  = 0;
                double[] xiSE = new double[x.ColumnCount];
                //coeff tstats
                double[] xiT = new double[x.ColumnCount];
                //lower value for pvalue
                double[] xiP = new double[x.ColumnCount];
                for (int i = 0; i < x.ColumnCount; i++)
                {
                    //use the matrix techniques shown on p 717 of Mendenhall and Sincich
                    sxx     = s * Math.Sqrt(xxminus1.Column(i)[i]);
                    xiSE[i] = sxx;
                    xiT[i]  = p[i] / sxx;
                    xiP[i]  = Shared.GetPValueForTDist(idfE, xiT[i], 0, 1);
                }
                double FCriticalValue    = 0;
                string FGreaterFCritical = string.Empty;
                if (_subalgorithm == Calculator1.MATH_SUBTYPES.subalgorithm8.ToString())
                {
                    //anova regression
                    //anova critical fvalue test
                    //FCriticalValue = ExcelFunctions.FInv(1 - _confidenceInt, idfR, idfE);
                    FCriticalValue    = ExcelFunctions.FInv(dbCI, idfR, idfE);
                    FGreaterFCritical = (FValue > FCriticalValue) ? "true" : "false";
                    SetAnovaIntervals(0, p, xiSE, tCriticalValue);
                    SetAnovaIntervals(1, p, xiSE, tCriticalValue);
                    SetAnovaIntervals(2, p, xiSE, tCriticalValue);
                }
                else
                {
                    //set QTM ci and pi intervals
                    SetQTIntervals(0, s, xxminus1, ci.Row(_scoreRows - 1).ToArray(), p, tCriticalValue);
                    SetQTIntervals(1, s, xxminus1, ci.Row(_scoreRows - 2).ToArray(), p, tCriticalValue);
                    SetQTIntervals(2, s, xxminus1, ci.Row(_scoreRows - 3).ToArray(), p, tCriticalValue);
                }
                //add the data to a string builder
                StringBuilder sb = new StringBuilder();
                sb.AppendLine("regression results");
                //dep var has to be in the 4 column always
                string sLine = string.Concat("dependent variable:  ", _colNames[3]);
                sb.AppendLine(sLine);
                string[] cols = new string[] { "source", "df", "SS", "MS" };
                sb.AppendLine(Shared.GetLine(cols, true));
                cols = new string[] { "model", dfR.ToString("F0"), SSR.ToString("F4"), MSR.ToString("F4") };
                sb.AppendLine(Shared.GetLine(cols, false));
                cols = new string[] { "error  ", dfE.ToString("F0"), SSE.ToString("F4"), MSE.ToString("F4") };
                sb.AppendLine(Shared.GetLine(cols, false));
                cols = new string[] { "total    ", (dfR + dfE).ToString("F0"), (SSR + SSE).ToString("F4") };
                sb.AppendLine(Shared.GetLine(cols, false));
                sb.AppendLine(string.Empty);
                cols = new string[] { "R-squared", rSquared.ToString("F4"), "Adj R-squared", adjRSquared.ToString("F4") };
                sb.AppendLine(Shared.GetLine(cols, false));
                cols = new string[] { "F value", FValue.ToString("F4"), "prob > F", pValue.ToString("F4") };
                sb.AppendLine(Shared.GetLine(cols, false));
                sb.AppendLine(string.Empty);
                cols = new string[] { GetName("variable"), "coefficient", "stand error", "T-ratio", "prob > T" };
                sb.AppendLine(Shared.GetLine(cols, true));
                for (int i = 0; i < p.Count(); i++)
                {
                    if (i == 0)
                    {
                        cols = new string[] { GetName(_depColNames[i]), p[i].ToString("F5"), xiSE[i].ToString("F4"), xiT[i].ToString("F4"), xiP[i].ToString("F4") };
                        sb.AppendLine(Shared.GetLine(cols, false));
                    }
                    else
                    {
                        cols = new string[] { GetName(_depColNames[i]), p[i].ToString("F5"), xiSE[i].ToString("F4"), xiT[i].ToString("F4"), xiP[i].ToString("F4") };
                        sb.AppendLine(Shared.GetLine(cols, false));
                    }
                }
                cols = new string[] { "durbin-watson: ", d.ToString("F4") };
                sb.AppendLine(Shared.GetLine(cols, false));
                if (_subalgorithm == Calculator1.MATH_SUBTYPES.subalgorithm8.ToString())
                {
                    cols = new string[] { "F Critical Value", FCriticalValue.ToString("F5"), "F > F Critical", FGreaterFCritical };
                    sb.AppendLine(Shared.GetLine(cols, true));
                    cols = new string[] { "estimate", "predicted", string.Concat("lower ", _confidenceInt.ToString(), "%"), string.Concat("upper ", _confidenceInt.ToString(), "%") };
                    sb.AppendLine(Shared.GetLine(cols, true));
                    cols = new string[] { "Col 0 Mean CI ", QTPredicted.ToString("F4"), QTL.ToString("F4"), QTU.ToString("F4") };
                    sb.AppendLine(Shared.GetLine(cols, false));
                    cols = new string[] { "Col 1 - 0 Mean CI ", QTPredicted10.ToString("F4"), QTL10.ToString("F4"), QTU10.ToString("F4") };
                    sb.AppendLine(Shared.GetLine(cols, false));
                    cols = new string[] { "Col 2 - 0 Mean CI ", QTPredicted20.ToString("F4"), QTL20.ToString("F4"), QTU20.ToString("F4") };
                    sb.AppendLine(Shared.GetLine(cols, false));
                }
                else
                {
                    cols = new string[] { "estimate", "predicted", string.Concat("lower ", _confidenceInt.ToString(), "%"), string.Concat("upper ", _confidenceInt.ToString(), "%") };
                    sb.AppendLine(Shared.GetLine(cols, true));
                    cols = new string[] { "QTM CI ", QTPredicted.ToString("F4"), QTL.ToString("F4"), QTU.ToString("F4") };
                    sb.AppendLine(Shared.GetLine(cols, false));
                    cols = new string[] { "QTM PI ", QTPredicted.ToString("F4"), (QTPredicted - QTPI).ToString("F4"), (QTPredicted + QTPI).ToString("F4") };
                    sb.AppendLine(Shared.GetLine(cols, false));
                    string sRow = string.Concat("row ", data.Count - 2);
                    cols = new string[] { sRow };
                    sb.AppendLine(Shared.GetLine(cols, true));
                    cols = new string[] { "CI ", QTPredicted10.ToString("F4"), QTL10.ToString("F4"), QTU10.ToString("F4") };
                    sb.AppendLine(Shared.GetLine(cols, false));
                    cols = new string[] { "PI ", QTPredicted10.ToString("F4"), (QTPredicted10 - QTPI10).ToString("F4"), (QTPredicted10 + QTPI10).ToString("F4") };
                    sb.AppendLine(Shared.GetLine(cols, false));
                    sRow = string.Concat("row ", data.Count - 1);
                    cols = new string[] { sRow };
                    sb.AppendLine(Shared.GetLine(cols, true));
                    cols = new string[] { "CI ", QTPredicted20.ToString("F4"), QTL20.ToString("F4"), QTU20.ToString("F4") };
                    sb.AppendLine(Shared.GetLine(cols, false));
                    cols = new string[] { "PI ", QTPredicted20.ToString("F4"), (QTPredicted20 - QTPI20).ToString("F4"), (QTPredicted20 + QTPI20).ToString("F4") };
                    sb.AppendLine(Shared.GetLine(cols, false));
                }
                if (this.MathResult.ToLower().StartsWith("http"))
                {
                    string sError    = string.Empty;
                    bool   bHasSaved = CalculatorHelpers.SaveTextInURI(
                        _params.ExtensionDocToCalcURI, sb.ToString(), this.MathResult, out sError);
                    if (!string.IsNullOrEmpty(sError))
                    {
                        this.MathResult += sError;
                    }
                }
                else
                {
                    this.MathResult = sb.ToString();
                }
            }
            catch (Exception ex)
            {
                this.ErrorMessage = ex.Message;
            }
        }
コード例 #24
0
        public bool Exists3()
        {
            try
            {
                var curve = _spectrum.SpectrumData.Where(p => p.X >= 560 && p.X <= 740).ToList();
                var x     = curve.Select(p => p.X).ToArray();
                var y     = curve.Select(p => p.Y).ToArray();
                var minY  = y.Min();
                var maxY  = y.Max();
                y     = y.Select(p => (p - minY) / (maxY - minY)).ToArray();
                curve = x.Zip(y, (xp, yp) => new System.Windows.Point(xp, yp)).ToList();

                //fit quadratic function betweek 560 and 612
                var curve1 = curve.Where(p => p.X >= 560 && p.X <= 612).ToList();
                var xq     = curve1.Select(p => p.X).ToArray();
                var yq     = curve1.Select(p => p.Y).ToArray();
                var p2     = Fit.Polynomial(xq, yq, 2);
                //y = p2[2]x^2 + p2[1]x + p2[0]
                var highestPoint = curve1.Where(p => p.Y == yq.Max()).First();

                //fit linear function between 560 and 590
                var    curve1a       = curve.Where(p => p.X >= 560 && p.X <= 590).ToList();
                var    xData         = curve1a.Select(p => p.X).ToArray();
                var    yData         = curve1a.Select(p => p.Y).ToArray();
                var    linear        = Fit.Line(xData, yData);
                double intercept     = linear.Item1;
                double slope         = linear.Item2;
                var    goodnessOfFit = GoodnessOfFit.RSquared(xData.Select(d => slope * d + intercept), yData);

                bool rule1 = (p2[2] < -0.00001) && (highestPoint.X > 580 && highestPoint.X < 610) &&
                             (slope > 0) && (goodnessOfFit > 0.85);
                if (!rule1)
                {
                    //fit quadratic function betweek 605 and 620
                    var curve1b = curve.Where(p => p.X >= 605 && p.X <= 620).ToList();
                    xq = curve1b.Select(p => p.X).ToArray();
                    yq = curve1b.Select(p => p.Y).ToArray();
                    p2 = Fit.Polynomial(xq, yq, 2);
                    //y = p2[2]x^2 + p2[1]x + p2[0]
                    var lowestPointX = Math.Round((-1 * p2[1]) / (2 * p2[2]));

                    bool rule1a = (p2[2] > 0.0003) && (lowestPointX > 610) && (lowestPointX < 615);
                    if (!rule1a)
                    {
                        return(false);
                    }
                }


                //fit quadratic function between highestPoints
                var curve2        = curve.Where(p => p.X >= 628 && p.X <= 638).ToList();
                var xs            = curve2.Select(p => p.X).ToArray();
                var ys            = curve2.Select(p => p.Y).ToArray();
                var highestPoint1 = curve2.Where(p => p.Y == ys.Max()).First();
                curve2 = curve.Where(p => p.X >= 605 && p.X <= highestPoint1.X).ToList();
                xs     = curve2.Select(p => p.X).ToArray();
                ys     = curve2.Select(p => p.Y).ToArray();
                p2     = Fit.Polynomial(xs, ys, 2);
                //y = p2[2]x^2 + p2[1]x + p2[0]
                var criticalPointX = Math.Round((-1 * p2[1]) / (2 * p2[2]));
                var lowestPoint    = curve2.Where(p => p.Y == ys.Min()).First();

                //for (int i = 0; i < xs.Length; i++)
                //{
                //    String s = String.Format("{0},{1},{2}", xs[i], ys[i],
                //        Polynomial.Evaluate(xs[i], p2));
                //    Debug.WriteLine(s);
                //}


                bool rule2 = (p2[2] > 0) && ((criticalPointX > 609 && criticalPointX < 619) ||
                                             (lowestPoint.X >= 611 && lowestPoint.X <= 615));
                if (!rule2)
                {
                    return(false);
                }


                //fit linear function between 640 and 740
                var curve3 = curve.Where(p => p.X >= 640 && p.X <= 740).ToList();
                xData         = curve3.Select(p => p.X).ToArray();
                yData         = curve3.Select(p => p.Y).ToArray();
                linear        = Fit.Line(xData, yData);
                intercept     = linear.Item1;
                slope         = linear.Item2;
                goodnessOfFit = GoodnessOfFit.RSquared(xData.Select(d => slope * d + intercept), yData);

                bool rule3 = (slope > 0) && (goodnessOfFit > 0.9);
                if (!rule3)
                {
                    return(false);
                }

                return(true);
            }
            catch
            {
            }

            return(true);
        }