private bool CheckPair(TickDiffPair pair)
            {
                // Checks whether candidate tick diff pair should be accepted.
                // Not allowing pairs that are "too parallell"

                TickDiff     p0          = pair.TickDiff1;
                TickDiff     p1          = pair.TickDiff2;
                const double thetaThresh = 5;
                const double lambda      = 0.000001;

                // Using  dot product and a threshold on the angle theta
                // abs = ||a|| * ||b||
                // dot = a0*b0 + a1*b1
                //theta = arccos(dot/abs)
                double abs = Math.Sqrt(Math.Pow(p0.mLatDiff, 2) + Math.Pow(p0.mLongDiff, 2)) * Math.Sqrt(Math.Pow(p1.mLatDiff, 2) + Math.Pow(p1.mLongDiff, 2));
                double dot = p0.mLatDiff * p1.mLatDiff + p0.mLongDiff * p1.mLongDiff;

                List <double> diffs = new List <double>()
                {
                    p0.mLatDiff,
                    p1.mLatDiff,
                    p0.mLongDiff,
                    p1.mLongDiff
                };

                if (!diffs.TrueForAll(diff => Math.Abs(diff) > lambda))
                {
                    return(false);
                }

                double theta    = Math.Acos(dot / abs);
                double thetaDeg = toDegrees(theta);

                return(thetaDeg > thetaThresh && thetaDeg < 180 - thetaThresh);
            }
            private void RunSingleCalibration(TickDiffPair pair)
            {
                // Calculates mean and std for calibration factors for x and y
                double a0 = Math.Pow(pair.TickDiff1.mLatDiff, 2);
                double b0 = Math.Pow(pair.TickDiff1.mLongDiff, 2);
                double a1 = Math.Pow(pair.TickDiff2.mLatDiff, 2);
                double b1 = Math.Pow(pair.TickDiff2.mLongDiff, 2);
                double d0, d1;

                if (UseAlt)
                {
                    d0 = Math.Pow(pair.TickDiff1.mDist, 2) - Math.Pow(pair.TickDiff1.mAltDiff, 2);
                    d1 = Math.Pow(pair.TickDiff2.mDist, 2) - Math.Pow(pair.TickDiff2.mAltDiff, 2);
                }
                else
                {
                    d0 = Math.Pow(pair.TickDiff1.mDist, 2);
                    d1 = Math.Pow(pair.TickDiff2.mDist, 2);
                }

                double y = Math.Sqrt((a0 * d1 - a1 * d0) / (a0 * b1 - a1 * b0));
                double x = Math.Sqrt((d0 / a0) - (b0 * (a1 * d0 - a0 * d1)) / (a0 * (a1 * b0 - a0 * b1)));

                if (!Double.IsNaN(y) && !Double.IsNaN(x))
                {
                    // This should be controlled for already in FindCandidate()
                    pair.Prediction = new ConversionFactors(x, y);
                }
            }
            private List <TickDiffPair> FindCandidates(TrainingSession ts, int n, int ticksDiff = 1)
            {
                // Finds tickDiff pairs suitable for calibration

                int    ticks = ts.mTicks;
                Random rand  = new Random();
                List <TickDiffPair> tickDiffPairs = new List <TickDiffPair> {
                };
                HashSet <int> usedPoints          = new HashSet <int> {
                };

                while (tickDiffPairs.Count < n)
                {
                    TickDiff[] candidatePair = new TickDiff[2];
                    int[]      tickNumbers   = new int[2];
                    for (int k = 0; k < 2; k++)
                    {
                        bool foundCandidate = false;

                        while (!foundCandidate)
                        {
                            // Comparing the tick with the next tick
                            tickNumbers[k] = rand.Next(0, ticks - (ticksDiff + 1));
                            bool isUsed     = usedPoints.Contains(tickNumbers[k]);
                            bool altSuccess = Math.Abs(ts.mAltVector[tickNumbers[k]] - ts.mAltVector[tickNumbers[k] + ticksDiff]) > AltThresh;
                            if (!isUsed || altSuccess)
                            {
                                TickDiff candidate;
                                try
                                {
                                    candidate = new TickDiff(ts, tickNumbers[k], ticksDiff);
                                }
                                catch (NullReferenceException e)
                                {
                                    continue;
                                }
                                catch (NoDistanceDiffException e)
                                {
                                    continue;
                                }
                                candidatePair[k] = candidate;
                                foundCandidate   = true;
                            }
                        }
                    }
                    TickDiffPair tickDiffPair = new TickDiffPair(candidatePair[0], candidatePair[1]);
                    if (CheckPair(tickDiffPair))
                    {
                        tickDiffPairs.Add(tickDiffPair);
                        // Adding the first tick in each tickDiff used tickDiffs
                        usedPoints.Add(tickNumbers[0]);
                        usedPoints.Add(tickNumbers[1]);
                    }
                }
                return(tickDiffPairs);
            }
 private void CalculateCalibrationError(TickDiffPair predictionPair, List <TickDiffPair> validationSet)
 {
     predictionPair.Error = CalculateCalibrationError(predictionPair.Prediction, validationSet);
 }