Example #1
0
        private Dictionary <string, object> GetWebData(int objectID, FaultRateInfo.ObjectType objectType, int months, Dictionary <int, int> eqptContractCount, Dictionary <int, int> repairCount)
        {
            months = months > 120 ? 120 - 1 : months - 1;
            Dictionary <string, object> result = new Dictionary <string, object>();
            List <FaultRateInfo>        ForecastRateList = new List <FaultRateInfo>();
            double slope = 0, intercept = 0, slope1 = 0, intercept1 = 0;

            List <FaultRateInfo> RateList = new List <FaultRateInfo>();
            List <FaultRateInfo> RateList1 = new List <FaultRateInfo>();

            GetRateList(objectID, objectType, eqptContractCount, repairCount, months, out RateList, out RateList1);

            if (RateList.Count >= 2)
            {
                Tuple <double, double> solpAndIntercept1 = SimpleRegression.Fit(RateList.Select(item => SQLUtil.ConvertDouble((item.Year - 1) * 12 + (int)item.Month)).ToArray(), RateList.Select(item => item.Rate).ToArray());
                slope     = solpAndIntercept1.Item1;
                intercept = solpAndIntercept1.Item2;
            }

            if (RateList1.Count >= 2)
            {
                Tuple <double, double> solpAndIntercept2 = SimpleRegression.Fit(RateList1.Select(item => SQLUtil.ConvertDouble((item.Year - 1) * 12 + (int)item.Month)).ToArray(), RateList1.Select(item => item.Rate).ToArray());
                slope1     = solpAndIntercept2.Item1;
                intercept1 = solpAndIntercept2.Item2;
            }

            ForecastRateList = GetForecastRate(objectID, objectType, slope, intercept, slope1, intercept1, months);

            result.Add("RateList", RateList);
            result.Add("RateList1", RateList1);
            result.Add("ForecastRateList", ForecastRateList);
            result.Add("WebData", ForecastRateList.Concat(RateList).Concat(RateList1));

            return(result);
        }
Example #2
0
        private Tuple <double, double> AllCases(double hr50, double hr85)
        {
            var validReadings = dataResult.Where(el => el <hr85 && el> hr50);
            var underReadings = dataResult.Where(el => el < hr85);
            var aboveReadings = dataResult.Where(el => el > hr50);

            if (underReadings.Count() == 0 || aboveReadings.Count() == 0 || validReadings.Count() < 2)
            {
                MessageBox.Show("All readings are invalid, we cannot determine your Aerobic Capacity");
                return(null);
            }

            var xdata = new List <double>();
            var ydata = new List <double>();

            for (int i = 0; i < dataResult.Count; i++)
            {
                if (dataResult[i] < hr50 || dataResult[i] > hr85)
                {
                    continue;
                }
                ydata.Add(dataResult[i]);
                xdata.Add((double)Tools.StepToAerobic(i, stepHeight));
            }
            return(SimpleRegression.Fit(xdata.ToArray(), ydata.ToArray()));
        }
Example #3
0
        /// <summary>
        /// Gets the specified user identifier.
        /// </summary>
        /// <param name="userId">The user identifier.</param>
        /// <returns></returns>
        public IActionResult Get([FromQuery] Guid userId, [FromQuery] Guid procedureId, [FromQuery] Guid scenarioId)
        {
            try
            {
                IQueryable <TrialAnalysis> query = this._repository.GetTrialAnalysis();

                if (userId != Guid.Empty)
                {
                    query = query.Where(a => a.UserId == userId);
                }

                if (procedureId != Guid.Empty)
                {
                    query = query.Where(a => a.ProcedureId == procedureId);
                }

                if (scenarioId != Guid.Empty)
                {
                    query = query.Where(a => a.ScenarioId == scenarioId);
                }

                List <TrialAnalysis> result = query.ToList();
                double[]             y      = result.Select(t => (double)t.Milliseconds / 1000).ToArray();
                double[]             x      = result.Select(t => Math.Log((2.0 * t.Distance) / t.Width, 2)).ToArray();

                Tuple <double, double> fit = SimpleRegression.Fit(x, y);

                return(Ok(new { A = fit.Item1, B = fit.Item2 }));
            }
            catch (Exception ex)
            {
                this._logger.LogError(0, ex, ex.Message);
                throw;
            }
        }
Example #4
0
        public static Line FitLine2D(List <double> xs, List <double> ys)
        {
            var yDeviation = ys.StandardDeviation();
            var xDeviation = xs.StandardDeviation();
            var isVertical = yDeviation > xDeviation;

            if (isVertical)
            {
                Swap(ref xs, ref ys);
            }

            var biasAndWeight = SimpleRegression.Fit(xs.ToArray(), ys.ToArray());
            var bias          = biasAndWeight.Item1;
            var weight        = biasAndWeight.Item2;

            var xStart = xs.Min();
            var xEnd   = xs.Max();

            var yStart = xStart * weight + bias;
            var yEnd   = xEnd * weight + bias;



            return(new Line(isVertical?yStart: xStart, isVertical ?xStart: yStart, isVertical ? yEnd: xEnd, isVertical ? xEnd: yEnd));
        }
Example #5
0
        /// <summary>
        /// Least-Squares fitting the points (x,y) to a line y : x -> a+b*x,
        /// returning a function y' for the best fitting line.
        /// </summary>
        public static Func <double, double> LineFunc(double[] x, double[] y)
        {
            var    parameters = SimpleRegression.Fit(x, y);
            double intercept = parameters.Item1, slope = parameters.Item2;

            return(z => intercept + slope * z);
        }
        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));
        }
Example #7
0
        private void FitLineRegression(double[] xs, double[] ys, out HTuple lineX1, out HTuple lineY1,
                                       out HTuple lineX2, out HTuple lineY2)
        {
            var lineResult = SimpleRegression.Fit(xs, ys);
            var bias       = lineResult.Item1;
            var weight     = lineResult.Item2;

            HalconScripts.ImageLineIntersections(weight, bias, _width, _height, out lineX1, out lineY1, out lineX2,
                                                 out lineY2);
        }
Example #8
0
        /*------------ STATIC METHODS ------------------*/

        public static double MeasureSlope(PartLocation[] list)
        {
            // Fit  to linear regression // y:x->a+b*x
            Double[] Xs = list.Select(xx => xx.X).ToArray();
            Double[] Ys = list.Select(xx => xx.Y).ToArray();
            Tuple <double, double> result = SimpleRegression.Fit(Xs, Ys);

            //x.a = result.Item1; //this should be as close to zero as possible if things worked correctly
            return(result.Item2); //this represents the slope of the tape
        }
Example #9
0
        public BETA(kdata data, kdata index)
        {
            var q = from i in index
                    join s in data on i.date equals s.date
                    select new { stock = s.close, index = i.close };

            var ret = SimpleRegression.Fit(
                pct(q.Select(p => p.index).ToArray()),
                pct(q.Select(p => p.stock).ToArray()));

            alpha = ret.Item1;
            beta  = ret.Item2;
        }
Example #10
0
        public static double Slope(double[] values, int startIndex, int length)
        {
            var x = new double[length];
            var y = new double[length];

            for (var i = 0; i < length; i++)
            {
                x[i] = startIndex + i;
                y[i] = values[startIndex + i];
            }

            var(a, b) = SimpleRegression.Fit(x, y);
            return(-b);
        }
        public double Correlation(double[] xArray, double[] yArray)
        {
            SimpleRegression regression = new SimpleRegression();

            if (xArray.Length != yArray.Length)
            {
                //TODO throw new DimensionMismatchException(xArray.length, yArray.length);
            }
            if (xArray.Length < 2)
            {
                //TODO throw new MathIllegalArgumentException(LocalizedFormats.INSUFFICIENT_DIMENSION, new Object[] { Integer.valueOf(xArray.length), Integer.valueOf(2) });
            }
            for (int i = 0; i < xArray.Length; i++)
            {
                regression.AddData(xArray[i], yArray[i]);
            }
            return(regression.GetR());
        }
Example #12
0
        static double kRatio(StatisticsCollector collector)
        {
            var pnl = collector.pnl();

            if (all(pnl, p => p == 0))
            {
                return(0);
            }

            var equity     = cumulativeSum(pnl);
            var regression = new SimpleRegression();

            eachIt(equity, (i, p) => regression.addData(i + 1, p));
            var b1       = regression.getSlope();
            var stdError = regression.getSlopeStdErr();

            return(b1 / (stdError * Math.Sqrt(pnl.Count)));
        }
Example #13
0
        private double FixationSlope(List <Fixation> fixations)
        {
            List <Tuple <double, double> > samples = new List <Tuple <double, double> >();

            foreach (var fixation in fixations)
            {
                Tuple <double, double> sample = new Tuple <double, double>(fixation.x, fixation.y);
                samples.Add(sample);
            }

            if (samples.Count >= 2)
            {
                Tuple <double, double> result = SimpleRegression.Fit(samples);
                return(result.Item2);
            }
            else
            {
                return(0);
            }
        }
Example #14
0
        public void FitsToBestLineThroughOrigin()
        {
            // Mathematica: Fit[{{1,4.986},{2,2.347},{3,2.061},{4,-2.995},{5,-2.352},{6,-5.782}}, {x}, x]
            // -> -0.467791 x

            var x = Enumerable.Range(1, 6).Select(Convert.ToDouble).ToArray();
            var y = new[] { 4.986, 2.347, 2.061, -2.995, -2.352, -5.782 };

            var resp = Fit.LineThroughOrigin(x, y);

            Assert.AreEqual(-0.467791, resp, 1e-4);

            var resf = Fit.LineThroughOriginFunc(x, y);

            foreach (var z in Enumerable.Range(-3, 10))
            {
                Assert.AreEqual(-0.467791 * z, resf(z), 1e-4);
            }

            var respSeq = SimpleRegression.FitThroughOrigin(Generate.Map2(x, y, Tuple.Create));

            Assert.AreEqual(-0.467791, respSeq, 1e-4);
        }
        public double GetTrend(List <EDFSample> samples)
        {
            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++;
            }
            if (Time.Length > 1)
            {
                double result = SimpleRegression.Fit(Time, Amount).Item2;

                return(result);
            }
            else
            {
                return(0);
            }
        }
        /// <summary>
        ///  计算策略的各项性能指标,目前胜率等和交易次数相关的指标只针对非仓位管理型的策略
        /// 该性能统计默认为是对日频采样的统计,若为其他频率需调整barsOfYear
        /// 所有指标保留四位小数
        /// 若未穿入benchmark
        /// </summary>
        /// <param name="accountHistory"></param>
        /// <param name="positions"></param>
        /// <param name="benchmark"></param>
        /// <param name="riskFreeRate"></param>
        /// <returns></returns>
        public static PerformanceStatisics compute(List <BasicAccount> accountHistory, SortedDictionary <DateTime, Dictionary <string, PositionsWithDetail> > positions, double[] benchmark = null, double riskFreeRate = 0.00)
        {
            //若没有输入benchmark,构建默认的benchmark(全为1)3
            int sign0 = 0;

            if (benchmark == null)
            {
                benchmark = new double[accountHistory.Count];
                for (; sign0 < accountHistory.Count; sign0++)
                {
                    benchmark[sign0] = 1;
                }
            }
            //benchmark与净值数据不匹配时跳出
            if (benchmark.Length != accountHistory.Count)
            {
                Console.WriteLine("The length of benchmark is not consistent with accountHistory!");
                return(null);
            }
            PerformanceStatisics performanceStats = new PerformanceStatisics();

            //无风险收益率(年化)
            double barsOfYear = 252;
            //account长度,account记录周期数
            int lengthOfAccount = accountHistory.Count;
            //初始资产
            double intialAssets = accountHistory[0].totalAssets;

            //净值
            double[] netWorth = accountHistory.Select(a => a.totalAssets / intialAssets).ToArray();
            //收益率与超额收益率,比净值数少一
            double[] returnArray             = new double[netWorth.Length - 1]; //收益率
            double[] returnArrayOfBenchmark  = new double[netWorth.Length - 1]; //基准收益率
            double[] benchmarkExcessReturn   = new double[returnArray.Length];  //基准收益率 - 无风险收益率
            double[] excessReturnToBenchmark = new double[returnArray.Length];  //收益率 - 基准收益率
            double[] excessReturnToRf        = new double[returnArray.Length];  //收益率 - 无风险收益率
            double[] timeIndexList           = new double[netWorth.Length];     //时间标签tick
            for (int i = 0; i < returnArray.Length; i++)
            {
                returnArray[i]             = (netWorth[i + 1] - netWorth[i]) / netWorth[i];
                returnArrayOfBenchmark[i]  = (benchmark[i + 1] - benchmark[i]) / benchmark[i];
                excessReturnToRf[i]        = returnArray[i] - riskFreeRate / barsOfYear;
                benchmarkExcessReturn[i]   = returnArrayOfBenchmark[i] - riskFreeRate / barsOfYear;
                excessReturnToBenchmark[i] = returnArray[i] - returnArrayOfBenchmark[i];
                timeIndexList[i]           = i;
            }
            timeIndexList[timeIndexList.Length - 1] = timeIndexList.Length - 1;
            //交易次数
            double numOfTrades = 0;
            //成功交易次数
            double numOfSuccess = 0;
            //失败交易次数
            double numOfFailure = 0;
            //累计盈利
            double cumProfit = 0;
            //累计亏损
            double cumLoss = 0;

            //交易统计
            foreach (var date in positions.Keys)
            {
                foreach (var variety in positions[date].Keys)
                {
                    //交易笔数累计(一组相邻的反向交易为一笔交易)
                    numOfTrades += positions[date][variety].record.Count / 2;
                    //成功交易笔数累计
                    //  List<TransactionRecord> lastestRecord = new List<TransactionRecord>(positions[date][variety].record[positions[date][variety].record.Count -1])
                    for (int rec = 1; rec < positions[date][variety].record.Count; rec += 2)
                    {
                        var nowRec  = positions[date][variety].record[rec];
                        var lastRec = positions[date][variety].record[rec - 1];
                        //若当前为平多,则平多价格大于开多价格,成功数+1;
                        //若当前为平空,则平空价格小于于开空价格,成功数+1
                        if ((nowRec.volume < 0 && nowRec.price > lastRec.price) || (nowRec.volume > 0 && nowRec.price < lastRec.price))
                        {
                            //成功计数
                            numOfSuccess++;
                            //收益累加
                            cumProfit += nowRec.volume < 0 ? (nowRec.price - lastRec.price) * Math.Abs(nowRec.volume) : (-nowRec.price + lastRec.price) * Math.Abs(nowRec.volume);
                        }
                        else
                        {
                            //亏损累加
                            cumLoss += nowRec.volume < 0 ? (nowRec.price - lastRec.price) * Math.Abs(nowRec.volume) : (-nowRec.price + lastRec.price) * Math.Abs(nowRec.volume);
                        }
                    }
                }
            }
            numOfFailure = numOfTrades - numOfSuccess;

            // netProfit
            performanceStats.netProfit = Math.Round((accountHistory[lengthOfAccount - 1].totalAssets - intialAssets), 4);

            //perNetProfit
            performanceStats.perNetProfit = Math.Round((performanceStats.netProfit / numOfTrades), 4);

            //totalReturn
            performanceStats.totalReturn = Math.Round((performanceStats.netProfit / intialAssets), 4);

            //anualReturn
            double daysOfBackTesting = accountHistory.Count;

            performanceStats.anualReturn = Math.Round((performanceStats.totalReturn / (daysOfBackTesting / barsOfYear)), 4);

            //anualSharpe
            performanceStats.anualSharpe = Math.Round(((returnArray.Average() - riskFreeRate / barsOfYear) / Statistics.StandardDeviation(returnArray) * Math.Sqrt(252)), 4);

            //winningRate
            performanceStats.winningRate = Math.Round((numOfSuccess / numOfTrades), 4);

            //PnLRatio
            performanceStats.PnLRatio = Math.Round((cumProfit / Math.Abs(cumLoss)), 4);

            //maxDrawDown
            performanceStats.maxDrawDown = Math.Round(computeMaxDrawDown(netWorth.ToList()), 4);

            //maxProfitRate
            performanceStats.maxProfitRatio = Math.Round(computeMaxProfitRate(netWorth.ToList()), 4);

            //profitMDDRatio
            performanceStats.profitMDDRatio = Math.Round((performanceStats.totalReturn / performanceStats.maxDrawDown), 4);

            //informationRatio

            performanceStats.informationRatio = Math.Round((excessReturnToBenchmark.Average() / Statistics.StandardDeviation(excessReturnToBenchmark) * Math.Sqrt(barsOfYear)), 4);

            //alpha
            var regstats = SimpleRegression.Fit(benchmarkExcessReturn, excessReturnToRf);

            performanceStats.alpha = Math.Round(regstats.Item1, 4);

            //beta
            performanceStats.beta = Math.Round(regstats.Item2, 4);

            //rSquare
            performanceStats.rSquare = Math.Round(Math.Pow(Correlation.Pearson(timeIndexList, netWorth), 2), 4);

            //averageHoldingRate
            double barsOfHolding = 0;

            double[] positionRate = new double[accountHistory.Count];
            int      sign         = 0;

            foreach (var accout in accountHistory)
            {
                if (accout.positionValue != 0)
                {
                    barsOfHolding++;
                }
                positionRate[sign] = accout.positionValue / accout.totalAssets;
                sign++;
            }

            performanceStats.averageHoldingRate = Math.Round((barsOfHolding / accountHistory.Count), 4);

            //averagePositionRate
            performanceStats.averagePositionRate = Math.Round(positionRate.Average(), 4);

            return(performanceStats);
        }
Example #17
0
 /// <summary>
 /// Least-Squares fitting the points (x,y) to a line y : x -> a+b*x,
 /// returning a function y' for the best fitting line.
 /// </summary>
 public static Func <double, double> LineFunc(double[] x, double[] y)
 {
     (double intercept, double slope) = SimpleRegression.Fit(x, y);
     return(z => intercept + slope * z);
 }
Example #18
0
        /// <summary>
        /// Least-Squares fitting the points (x,y) to a line through origin y : x -> b*x,
        /// returning a function y' for the best fitting line.
        /// </summary>
        public static Func <double, double> LineThroughOriginFunc(double[] x, double[] y)
        {
            double slope = SimpleRegression.FitThroughOrigin(x, y);

            return(z => slope * z);
        }
Example #19
0
 /// <summary>
 /// Least-Squares fitting the points (x,y) to a line through origin y : x -> b*x,
 /// returning its best fitting parameter b,
 /// where the intercept is zero and b the slope.
 /// </summary>
 public static double LineThroughOrigin(double[] x, double[] y)
 {
     return(SimpleRegression.FitThroughOrigin(x, y));
 }
Example #20
0
 /// <summary>
 /// Least-Squares fitting the points (x,y) to a line y : x -> a+b*x,
 /// returning its best fitting parameters as [a, b] array,
 /// where a is the intercept and b the slope.
 /// </summary>
 public static Tuple <double, double> Line(double[] x, double[] y)
 {
     return(SimpleRegression.Fit(x, y));
 }
        private static PartLocation DoCameraCalibration(VideoProcessing vp, PartLocation movement)
        {
            var cnc      = Global.Instance.cnc;
            var distance = new List <PartLocation>();
            var pixels   = new List <PartLocation>();

            // turn on slack compensation
            var savedSlackCompensation = cnc.SlackCompensation;

            cnc.SlackCompensation = true;

            var startingPos = cnc.XYLocation;

            startingPos.A = 0;

            vp.MarkA.Clear();

            for (int i = -4; i < 5; i++)
            {
                //move
                var newLocation = startingPos + (i * movement);
                if (!cnc.CNC_XYA(newLocation))
                {
                    return(null);
                }

                //try 5 times to find a circle
                List <Shapes.Circle> circles = new List <Shapes.Circle>();
                for (int tries = 5; tries > 0 && circles.Count == 0; tries--)
                {
                    circles = VideoDetection.FindCircles(vp);
                }
                if (circles.Count == 0)
                {
                    continue;                     //not found, move and try again
                }
                //find largest circle of the bunch
                var circle = circles.Aggregate((c, d) => c.Radius > d.Radius ? c : d); //find largest circle if we have multiple
                //  var circlePL = (1 / zoom) * circle.ToPartLocation(); //compensate for zoom
                circle.ToScreenUnzoomedResolution();
                distance.Add(newLocation);
                pixels.Add(circle.ToPartLocation());

                vp.MarkA.Add(circle.Clone().ToScreenResolution().ToPartLocation().ToPointF());
                //DisplayText(String.Format("Actual Loc = {0}\t Measured Loc = {1}", newLocation, UpCamera.PixelsToActualLocation(circlePL)), Color.Blue);
            }


            double XmmPerPixel = 0, YmmPerPixel = 0;

            if (pixels.Count < 2)
            {
                Global.Instance.mainForm.ShowMessageBox("Unable To Detect Circles",
                                                        "Try to adjust upcamera processing to see circles, and ensure upcamera needle position is correctly configured",
                                                        MessageBoxButtons.OK);
            }
            else
            {
                // Do regression on X and Y
                var Xs     = pixels.Select(xx => xx.X).ToArray();
                var Ys     = distance.Select(xx => xx.X).ToArray();
                var result = SimpleRegression.Fit(Xs, Ys);
                XmmPerPixel = result.Item2;

                Xs          = pixels.Select(xx => xx.Y).ToArray();
                Ys          = distance.Select(xx => xx.Y).ToArray();
                result      = SimpleRegression.Fit(Xs, Ys);
                YmmPerPixel = result.Item2;


                Global.Instance.DisplayText(String.Format("{0} Xmm/pixel   {1} Ymm/pixel", XmmPerPixel, YmmPerPixel), Color.Purple);

                // Now move to the center

                /* need to get gotolocation upcamera working still
                 * double X, Y; //error offset
                 * GotoUpCamPosition_button_Click(null, null);
                 * for (int tries = 5; tries > 0; tries--) {
                 *   if (GoToLocation_m(UpCamera, Shapes.ShapeTypes.Circle, 1.8, 0.5, out X, out Y)) {
                 *       Properties.Settings.Default.UpCam_PositionX = Cnc.CurrentX + X;
                 *       Properties.Settings.Default.UpCam_PositionY = Cnc.CurrentY - Y;
                 *       UpcamPositionX_textBox.Text = Properties.Settings.Default.UpCam_PositionX.ToString("0.00", CultureInfo.InvariantCulture);
                 *       UpcamPositionY_textBox.Text = Properties.Settings.Default.UpCam_PositionY.ToString("0.00", CultureInfo.InvariantCulture);
                 *
                 *   }
                 * }
                 */
            }

            //restore settings
            cnc.SlackCompensation = savedSlackCompensation;
            vp.MarkA.Clear();
            //return value
            return((pixels.Count < 2) ? null : new PartLocation(Math.Abs(XmmPerPixel), Math.Abs(YmmPerPixel)));
        }
Example #22
0
        public bool CalibrateTape(TapeObj x)
        {
            // Setup Camera

            if (x.FirstHole == null && x.FirstPart == null)
            {
                x.FirstHole = Cnc.XYLocation;                                             //defaults to hole based calibration
            }
            if (x.FirstHole != null)
            {
                SetCurrentTapeMeasurement(x.TapeType);
            }

            List <PartLocation> holes     = new List <PartLocation>();
            List <int>          holeIndex = new List <int>();

            if (x.FirstHole != null)
            {
                //1 - ensure first hole is correct
                MainForm.DisplayText("Moving to first hole @ " + x.FirstHole, Color.Purple);
                if (!MainForm.Cnc.CNC_XY(x.FirstHole))
                {
                    return(false);
                }
                var holepos = MainForm.FindPositionAndMoveToClosest(Shapes.ShapeTypes.Circle, 1.8, 0.1); //find this hole with high precision
                if (holepos == null)
                {
                    return(false);
                }
                x.FirstHole = holepos;
                MainForm.DisplayText("Found new hole locaiton @ " + x.FirstHole, Color.Purple);

                // move to first hole for shits & giggles
                if (!MainForm.Cnc.CNC_XY(x.FirstHole))
                {
                    return(false);
                }

                holes.Add(x.FirstHole);
                holeIndex.Add(0);
            }

            //2 - Look for for a few more holes
            //    XXX-should be adjsuted to acocomodate smaller strips
            if (x.FirstHole != null)
            {
                for (int i = 2; i < 8; i += 2)
                {
                    /* - hole based detection - */
                    /****************************/
                    if (!MainForm.Cnc.CNC_XY(x.GetHoleLocation(i)))
                    {
                        break;
                    }
                    Thread.Sleep(500);
                    var loc = MainForm.FindPositionAndMoveToClosest(Shapes.ShapeTypes.Circle, 1.8, 0.2);
                    if (loc == null)
                    {
                        break;
                    }
                    holes.Add(loc);
                    holeIndex.Add(i);
                }
            }
            else
            {
                for (int i = 0; i < 8; i += 1)
                {
                    /* - part based detection - */
                    /****************************/
                    if (x.FirstPart != null)
                    {
                        if (!MainForm.Cnc.CNC_XY(x.GetPartBasedLocation(i)))
                        {
                            break;
                        }
                        Thread.Sleep(500);
                        var loc = MainForm.FindPositionAndMoveToClosest(Shapes.ShapeTypes.Fiducial, 1.8, 0.2, x.TemplateFilename, .8);
                        if (loc == null)
                        {
                            break;
                        }
                        holes.Add(loc);
                        holeIndex.Add(i);
                    }
                }
            }
            if (holes.Count < 2)
            {
                return(false);                 // didn't get enough points to calibrate this one
            }
            //3 - Do Linear Regression on data if we have 2+ points
            // Fit circle to linear regression // y:x->a+b*x
            Double[] Xs = holes.Select(xx => xx.X - ((x.FirstHole != null) ? x.FirstHole.X : x.FirstPart.X)).ToArray();
            Double[] Ys = holes.Select(xx => xx.Y - ((x.FirstHole != null) ? x.FirstHole.Y : x.FirstPart.Y)).ToArray();
            Tuple <double, double> result = SimpleRegression.Fit(Xs, Ys);

            x.a     = result.Item1; //this should be as close to zero as possible if things worked correctly
            x.Slope = result.Item2; //this represents the slope of the tape
            MainForm.DisplayText(String.Format("Linear Regression: {0} + (0,{1})+(0,{2})x", x.FirstHole, x.a, x.Slope), Color.Brown);

            //4 - Determine Avg Hole Spacing
            double spacing = 0;

            for (int i = 0; i < holes.Count - 1; i++)
            {
                spacing += holes[i].DistanceTo(holes[i + 1]) / 2; //distance one hole to the next - /2 because we skip every other hole (step 2)
            }
            if (x.FirstHole != null)
            {
                x.HolePitch = spacing / (holes.Count - 1);                      //compute average for holes
            }
            else
            {
                x.PartPitch = 2 * spacing / (holes.Count - 1);
            }

            //5 - Done, specify that this is fully calibrated
            x.IsFullyCalibrated = true;

            MainForm.DisplayText("Tape " + x.ID + " Calibrated", Color.Brown);
            //MainForm.DisplayText(String.Format("\tEquation = {3} + (0,{0}) + {1} * ({2} * holeNumber)", x.a, x.b, x.HolePitch), System.Drawing.Color.Brown);

            MainForm.cameraView.DownCameraReset();
            if (!MainForm.Cnc.CNC_XY(x.FirstHole ?? x.FirstPart))
            {
                return(false);
            }

            return(true);
        }
Example #23
0
    public static List <Vector2Int> ComputeLSF(
        Color32 colId,
        float[] pixelsXF,
        float[] pixelsYF,
        float2 minXY,
        float2 maxXY,
        Texture2D provinceTex,
        out float[] midPointDistances,
        out bool isIdeal,
        int sampleResolution = 20,
        float minimumDistanceAlwaysHorizontal = 450f)
    {
        isIdeal = true;

        double[] xDouble = new double[pixelsXF.Length];
        double[] yDouble = new double[pixelsYF.Length];
        for (int i = 0; i < pixelsXF.Length; i++)
        {
            xDouble[i] = pixelsXF[i];
            yDouble[i] = pixelsYF[i];
        }

        System.Tuple <double, double> resH = SimpleRegression.Fit(xDouble, yDouble);
        int interceptH = Mathf.RoundToInt((float)resH.Item1 * provinceTex.width);

        System.Tuple <double, double> resV = SimpleRegression.Fit(yDouble, xDouble);
        int interceptV = Mathf.RoundToInt((float)resV.Item1 * provinceTex.height);

        float xRange = maxXY.x - minXY.x;
        float yRange = maxXY.y - minXY.y;

        int xRangeInt = Mathf.RoundToInt(xRange * provinceTex.width);
        int yRangeInt = Mathf.RoundToInt(yRange * provinceTex.height);

        int minX = Mathf.RoundToInt(minXY.x * provinceTex.width);
        int minY = Mathf.RoundToInt(minXY.y * provinceTex.height);

        //Sample the two lines we found using linear regression.
        Vector2Int[] horizontalLineSamples = GetLineSamples(
            false,
            sampleResolution,
            minX,
            minY,
            xRangeInt,
            yRangeInt,
            (float)resH.Item2,
            interceptH,
            0);

        Vector2Int[] verticalLineSamples = GetLineSamples(
            true,
            sampleResolution,
            minX,
            minY,
            xRangeInt,
            yRangeInt,
            (float)resV.Item2,
            interceptV,
            0);

        //Get the distance for which the line is inside of the province.
        float distanceH = GetLineThroughProvinceColorDistance(
            sampleResolution,
            provinceTex,
            horizontalLineSamples,
            colId);


        float distanceV = GetLineThroughProvinceColorDistance(
            sampleResolution,
            provinceTex,
            verticalLineSamples,
            colId);

        //see which line is longer
        float slope;
        int   intercept;
        float originalDistance;
        bool  vertical;

        if (distanceH >= distanceV || distanceH >= minimumDistanceAlwaysHorizontal)
        {
            slope            = (float)resH.Item2;
            intercept        = interceptH;
            vertical         = false;
            originalDistance = distanceH;
        }
        else
        {
            slope            = (float)resV.Item2;
            intercept        = interceptV;
            vertical         = true;
            originalDistance = distanceV;
        }

        //Create some lines parallel to the original line and compare distances
        int numParallelLines = 2; //every couple of lines are equally offset but on opposite sides

        float[] lineDistances = new float[1 + numParallelLines];
        lineDistances[0] = originalDistance;
        LineData[] lines = new LineData[1 + numParallelLines];
        //add original line
        lines[0] = new LineData(
            sampleResolution,
            minX,
            minY,
            xRangeInt,
            yRangeInt,
            slope,
            intercept,
            0);


        float offsetAmount = 0f;

        for (int i = 1; i <= numParallelLines; i++)
        {
            //LINE
            int sign = i % 2 == 0 ? -1 : 1;
            offsetAmount = i % 2 == 0 ? offsetAmount : offsetAmount + 0.1f;
            int offset = Mathf.RoundToInt(i * offsetAmount * xRangeInt) * sign;
            verticalLineSamples = GetLineSamples(
                vertical,
                sampleResolution,
                minX,
                minY,
                xRangeInt,
                yRangeInt,
                slope,
                intercept,
                offset);
            lines[i] = new LineData(
                sampleResolution,
                minX,
                minY,
                xRangeInt,
                yRangeInt,
                slope,
                intercept,
                offset);

            //Put the distances of each line in an array.
            lineDistances[i] = GetLineThroughProvinceColorDistance(
                sampleResolution,
                provinceTex,
                verticalLineSamples,
                colId);
        }

        //find the max distance line
        float maxDistance      = 0f;
        int   longestLineIndex = 0;

        for (int i = 0; i < lineDistances.Length; i++)
        {
            if (lineDistances[i] > maxDistance)
            {
                maxDistance      = lineDistances[i];
                longestLineIndex = i;
            }
        }

        //along the longest line, create some offsets and sample lines perpendicular to those offsets
        LineData[]     offsetLines       = new LineData[3];
        Vector2Int[][] offsetLineSamples = new Vector2Int[3][];

        Vector2Int[] offsetPointOnLineArray = new Vector2Int[3];

        for (int i = 1; i <= 3; i++)
        {
            offsetLineSamples[i - 1] = new Vector2Int[sampleResolution];

            Vector2Int a = GetPointOnLine(lines[longestLineIndex], ((float)i / ((float)3 + 1)), vertical);
            offsetPointOnLineArray[i - 1] = a;

            /*GameObject go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
             * go.transform.localScale /= 3f;
             * go.transform.position = new Vector3(a.x * (100f / 8192f), 0f, a.y * (100f / 8192f));*/

            float perpSlope       = -1 * lines[longestLineIndex].slope;
            int   offsetIntercept = GetInterceptThroughPoint(perpSlope, a, !vertical);

            offsetLines[i - 1] = new LineData(
                sampleResolution,
                minX,
                minY,
                xRangeInt,
                yRangeInt,
                perpSlope,
                offsetIntercept,
                0);

            offsetLineSamples[i - 1] = GetLineSamples(
                !vertical,
                sampleResolution,
                minX,
                minY,
                xRangeInt,
                yRangeInt,
                perpSlope,
                offsetIntercept,
                0);
        }

        //get the midpoint of each perpendicular offset line
        List <Vector2Int> offsetMidpoints = new List <Vector2Int>();

        float[] offSetLineDistances = new float[3];

        for (int i = 0; i < 3; i++)
        {
            if (TryGetLineMidpointOverProvince(sampleResolution, offsetLineSamples[i], provinceTex, colId, out offSetLineDistances[i], out Vector2Int o))
            {
                offsetMidpoints.Add(o);
            }
        }

        //relax the midpoints a bit
        if (offsetMidpoints.Count == 3)
        {
            offsetMidpoints = RelaxMidpointSpline(lines[longestLineIndex], offsetMidpoints, 0.5f);
        }
        else if (offsetMidpoints.Count == 0 || offsetMidpoints.Count == 2)
        {
            isIdeal = false;

            int count = offsetMidpoints.Count;

            offsetMidpoints.Clear();

            float dist = Vector2.Distance(offsetPointOnLineArray[0], offsetPointOnLineArray[1]);

            for (int i = 0; i < offsetPointOnLineArray.Length; i++)
            {
                offsetMidpoints.Add(offsetPointOnLineArray[i]);
                offSetLineDistances[i] = dist;
            }

            ImproveCenteringOfTwoPointCase(offsetPointOnLineArray[0], offsetPointOnLineArray[2], provinceTex, colId, out offsetMidpoints, 40);
        }

        midPointDistances = offSetLineDistances;
        return(offsetMidpoints);
    }
Example #24
0
 /// <summary>
 /// Least-Squares fitting the points (x,y) to a line y : x -> a+b*x,
 /// returning its best fitting parameters as [a, b] array,
 /// where a is the intercept and b the slope.
 /// </summary>
 public static (double A, double B) Line(double[] x, double[] y)
 {
     return(SimpleRegression.Fit(x, y));
 }