Пример #1
0
        private void LinearFitOfAveragedModel(uint[,] intensity)
        {
            // First do a non linear fit to find X0 and Y0
            NonLinearFit(intensity, false);

            if (m_IsSolved)
            {
                // Then do a linear fit to find IBackground and IStarMax
                // I(x, y) = IBackground + IStarMax * Exp ( -((x - X0)*(x - X0) + (y - Y0)*(y - Y0)) / (r0 * r0))
                LinearRegression linearFit = new LinearRegression();

                double modelR = m_ModelFWHM / (2 * Math.Sqrt(Math.Log(2)));
                double modelRSquare = modelR * modelR;
                double[,] modelData = new double[m_MatrixSize, m_MatrixSize];

                for (int x = 0; x < m_MatrixSize; x++)
                    for (int y = 0; y < m_MatrixSize; y++)
                    {
                        double modelVal = Math.Exp(-((x - X0) * (x - X0) + (y - Y0) * (y - Y0)) / (modelRSquare));
                        modelData[x, y] = modelVal;
                        linearFit.AddDataPoint(modelVal, intensity[x, y]);
                    }
                linearFit.Solve();

                for (int x = 0; x < m_MatrixSize; x++)
                    for (int y = 0; y < m_MatrixSize; y++)
                    {
                        m_Residuals[x, y] = intensity[x, y] - linearFit.ComputeY(modelData[x, y]);
                    }

                m_IBackground = linearFit.B;
                m_IStarMax = linearFit.A;
                m_R0 = modelR;
            }
        }
Пример #2
0
        public static DateTime GetNetworkTimeFromMultipleServers(string[] ntpServers, out float latencyInMilliseconds, out int aliveServers, out bool timeUpdated)
        {
            latencyInMilliseconds = 0;
            aliveServers = 0;
            double asyncCoeff = 0;
            double referenceTimeError = 0;
            var deltaTicksList = new List<double>();
            double[] serverLatencies = new double[ntpServers.Length];
            int[] serverAttempts = new int[ntpServers.Length];

            for (int packerIndex = 0; packerIndex < Settings.Default.NumberOfNTPRequestsPerUpdate; packerIndex++)
            {
                if (ntpServers.Length > 2)
                {
                    var fit = new LinearRegression();

                    float latency = 0;

                    for (int i = 0; i < ntpServers.Length; i++)
                    {
                        long startQPTicks = 0;
                        long endQPTicks = 0;
                        try
                        {
                            DateTime reference = GetSingleNetworkTimeReference(ntpServers[i], ref startQPTicks, ref endQPTicks);

                            long startTicks = NTPTimeKeeper.GetUtcTimeTicksFromQPCTicksNoDrift(startQPTicks);
                            long endTicks = NTPTimeKeeper.GetUtcTimeTicksFromQPCTicksNoDrift(endQPTicks);

                            fit.AddDataPoint(endTicks - startTicks, reference.Ticks - startTicks);

                            latency += (float)new TimeSpan(endTicks - startTicks).TotalMilliseconds;
                            serverLatencies[i] += (float) new TimeSpan(endTicks - startTicks).TotalMilliseconds;
                            serverAttempts[i]++;
                            aliveServers++;
                        }
                        catch
                        { }
                    }

                    fit.Solve();

                    asyncCoeff += fit.A;
                    deltaTicksList.Add(fit.B);
                    referenceTimeError += fit.StdDev;
                    latencyInMilliseconds += (latency / fit.NumberOfDataPoints);
                }
                else
                {
                    float latency = 0;
                    float delta = 0;
                    float stdDev = 0;
                    aliveServers = 0;

                    for (int i = 0; i < ntpServers.Length; i++)
                    {
                        long startQPTicks = 0;
                        long endQPTicks = 0;
                        try
                        {
                            DateTime reference = GetSingleNetworkTimeReference(ntpServers[i], ref startQPTicks, ref endQPTicks);

                            long startTicks = NTPTimeKeeper.GetUtcTimeTicksFromQPCTicksNoDrift(startQPTicks);
                            long endTicks = NTPTimeKeeper.GetUtcTimeTicksFromQPCTicksNoDrift(endQPTicks);

                            DateTime currTime = new DateTime((startTicks + endTicks) / 2);

                            latency += (float)new TimeSpan(endTicks - startTicks).TotalMilliseconds;
                            delta += new TimeSpan(reference.Ticks - currTime.Ticks).Ticks;
                            stdDev += (endTicks - startTicks) / 4;
                            serverLatencies[i] += (float)new TimeSpan(endTicks - startTicks).TotalMilliseconds;
                            serverAttempts[i]++;
                            aliveServers++;
                        }
                        catch
                        { }
                    }

                    asyncCoeff += 1;
                    deltaTicksList.Add(delta / aliveServers);
                    referenceTimeError += (stdDev / aliveServers);
                    latencyInMilliseconds += (latency / aliveServers);
                }
            }

            asyncCoeff /= Settings.Default.NumberOfNTPRequestsPerUpdate;
            double deltaTicks = deltaTicksList.Average();
            double deltaTicksOneSigma = deltaTicksList.Count > 1 ? Math.Sqrt(deltaTicksList.Sum(t => (t - deltaTicks) * (t - deltaTicks)) / (deltaTicksList.Count - 1)) : 0;
            referenceTimeError /= Settings.Default.NumberOfNTPRequestsPerUpdate;
            latencyInMilliseconds /= Settings.Default.NumberOfNTPRequestsPerUpdate;

            lock (s_SyncLock)
            {
                double averageLatency = 0;
                double fiveSigmaLatency = 0;
                const int SLIDING_INTERVAL = 3;

                // Update the time if
                //    (1) This is one of the first 3 updates or
                //    (2) The average latency in ms is within the Math.Max(5-sigma latency, 5 ms) from the average of last 5 measurements
                bool updateTimeReference = s_LastFiveNTPLatencies.Count < SLIDING_INTERVAL;
                if (!updateTimeReference)
                {
                    averageLatency = s_LastFiveNTPLatencies.Average();
                    fiveSigmaLatency = 5 * Math.Sqrt(s_LastFiveNTPLatencies.Sum(t => (t - averageLatency) * (t - averageLatency)) / (SLIDING_INTERVAL - 1));
                    updateTimeReference = latencyInMilliseconds - averageLatency < Math.Max(fiveSigmaLatency, 5);
                    if (!updateTimeReference)
                    {
                        if (s_LastFiveNTPLatenciesAlt.Count >= SLIDING_INTERVAL)
                        {
                            s_LastFiveNTPLatencies.Clear();
                            s_LastFiveNTPLatencies.AddRange(s_LastFiveNTPLatencies.Take(SLIDING_INTERVAL));
                            updateTimeReference = true;
                        }
                        else
                            s_LastFiveNTPLatenciesAlt.Add(latencyInMilliseconds);
                    }
                }

                if (updateTimeReference && !s_LastRequstedUpdateSkipped && s_LastFiveNTPLatencies.Count >= SLIDING_INTERVAL)
                {
                    // One-time skip update if delta is bigger than the average latency OR if the latency error is bigger than half the latency
                    if (new TimeSpan((long) deltaTicks).TotalMilliseconds > latencyInMilliseconds ||
                        new TimeSpan((long) referenceTimeError).TotalMilliseconds > 0.5*latencyInMilliseconds)
                    {
                        updateTimeReference = false;
                        s_LastRequstedUpdateSkipped = true;
                        Trace.WriteLine("One time skip update triggered");
                    }
                }

                if (updateTimeReference && !double.IsNaN(s_AverageAsyncCoeff) && !double.IsNaN(s_FiveSigmaAverageAsyncCoeff))
                {
                    double currCoeffDiff = Math.Abs(asyncCoeff - s_AverageAsyncCoeff);
                    if (currCoeffDiff > s_FiveSigmaAverageAsyncCoeff &&
                        currCoeffDiff > s_AverageAsyncCoeff * 0.25)
                    {
                        updateTimeReference = false;
                        Trace.WriteLine(string.Format("Ignoring async coefficient outlier of {0:F2}. Average coeff = {1:F2}; 5-sigma = {2:F2}; 25% coeff diff = {3:F2}", asyncCoeff, s_AverageAsyncCoeff, s_FiveSigmaAverageAsyncCoeff, s_AverageAsyncCoeff * 0.25));
                    }
                }

                if (updateTimeReference && Settings.Default.NTPOutlierIgnore &&
                    Math.Abs(new TimeSpan((long) deltaTicks).TotalMilliseconds) > Settings.Default.NTPOutlierValue)
                {
                    updateTimeReference = false;
                    Trace.WriteLine(string.Format("Ignoring outlier bigger than {0:F1} ms", Settings.Default.NTPOutlierValue));
                }

                if (s_Last60AsyncCoefficients.Count > 1 && s_Last60AsyncCoefficients.Count < 10)
                {
                    if (Math.Sign(asyncCoeff) != Math.Sign(s_Last60AsyncCoefficients.Average()))
                    {
                        updateTimeReference = false;
                        Trace.WriteLine(string.Format("Ignoring value with async coeff of {0:F2} which has oposite direction than the current average coeff of {1:F2}", asyncCoeff, s_Last60AsyncCoefficients.Average()));
                    }
                }

                long freq = 0;
                Profiler.QueryPerformanceFrequency(ref freq);

                var individualLatencies = new StringBuilder("(Latencies: ");
                for (int i = 0; i < ntpServers.Length; i++)
                {
                    if (serverAttempts[i] > 0)
                        individualLatencies.AppendFormat("{0:F1} ms;", serverLatencies[i]/(serverAttempts[i]));
                    else
                        individualLatencies.Append("...;");

                    if (!double.IsNaN(s_AverageAsyncCoeff) && !double.IsNaN(s_FiveSigmaAverageAsyncCoeff))
                        individualLatencies.AppendFormat("; AsyncCoeff: {0:F2} +/- {1:F2} (5-sigma)", s_AverageAsyncCoeff, s_FiveSigmaAverageAsyncCoeff);
                }
                individualLatencies.Append(")");

                if (updateTimeReference)
                {
                    while (s_LastFiveNTPLatencies.Count >= SLIDING_INTERVAL) s_LastFiveNTPLatencies.RemoveAt(0);
                    s_LastFiveNTPLatencies.Add(latencyInMilliseconds);
                    s_LastFiveNTPLatenciesAlt.Clear();

                    NTPTimeKeeper.ProcessUTCTimeOffset((long)deltaTicks, (long)referenceTimeError, latencyInMilliseconds, !double.IsNaN(s_AverageAsyncCoeff));

                    Trace.WriteLine(string.Format("Time Updated: Delta = {0} ms +/- {1} ms. AsyncCoeff = {2}, Latency = {3} ms +/- {4} ms (Average: {5} ms +/- {6} ms), QPC Frequency = {7} (Time: {8} UT) {9}.",
                        new TimeSpan((long)deltaTicks).TotalMilliseconds.ToString("0.0"),
                        new TimeSpan((long)deltaTicksOneSigma).TotalMilliseconds.ToString("0.00"),
                        (1 / asyncCoeff).ToString("0.00"),
                        latencyInMilliseconds.ToString("0.0"),
                        new TimeSpan((long)referenceTimeError).TotalMilliseconds.ToString("0.0"),
                        averageLatency.ToString("0.0"),
                        fiveSigmaLatency.ToString("0.00"),
                        freq,
                        DateTime.UtcNow.ToString("HH:mm:ss"),
                        individualLatencies.ToString()));

                    s_LastRequstedUpdateSkipped = false;

                    s_Last60AsyncCoefficients.Add(asyncCoeff);
                    if (s_Last60AsyncCoefficients.Count > 60) s_Last60AsyncCoefficients.RemoveAt(0);
                    if (s_Last60AsyncCoefficients.Count > 10)
                    {
                        s_AverageAsyncCoeff = s_Last60AsyncCoefficients.Average();
                        s_FiveSigmaAverageAsyncCoeff = 5 * Math.Sqrt(s_Last60AsyncCoefficients.Sum(t => (t - s_AverageAsyncCoeff) * (t - s_AverageAsyncCoeff)) / (s_Last60AsyncCoefficients.Count - 1));
                    }

                    if (s_Last60AsyncCoefficients.Count < 10 && s_Last60AsyncCoefficients.Count >= 3)
                    {
                        // While still collecting up to 10 measurements for the async coefficients, we can reject everything which more than 50% away from the rest of the coefficients
                        for (int i = s_Last60AsyncCoefficients.Count - 1; i >= 0; i--)
                        {
                            double averageOfRest = s_Last60AsyncCoefficients.Where((xx, idx) => idx != i).Average();
                            if (Math.Abs(s_Last60AsyncCoefficients[i] - averageOfRest) > 0.5 * averageOfRest)
                                s_Last60AsyncCoefficients.RemoveAt(i);

                            if (s_Last60AsyncCoefficients.Count <= 3)
                                break;
                        }
                    }
                }
                else
                    Trace.WriteLine(string.Format("Time *NOT* Updated: Delta = {0} ms +/- {1} ms. AsyncCoeff = {2}, Latency = {3} ms +/- {4} ms (Average: {5} ms +/- {6} ms), QPC Frequency = {7} (Time: {8} UT) {9}.",
                        new TimeSpan((long)deltaTicks).TotalMilliseconds.ToString("0.0"),
                        new TimeSpan((long)deltaTicksOneSigma).TotalMilliseconds.ToString("0.00"),
                        (1 / asyncCoeff).ToString("0.00"),
                        latencyInMilliseconds.ToString("0.0"),
                        new TimeSpan((long)referenceTimeError).TotalMilliseconds.ToString("0.0"),
                        averageLatency.ToString("0.0"),
                        fiveSigmaLatency.ToString("0.00"),
                        freq,
                        DateTime.UtcNow.ToString("HH:mm:ss"),
                         individualLatencies.ToString()));

                timeUpdated = updateTimeReference;
            }

            // If we are also timestamping with Window's time then we should update the system clock every time too
            if (timeUpdated && Settings.Default.RecordSecondaryTimeStampInAavFile)
            {
                DateTime currCorrectWindowsTime = DateTime.UtcNow.AddTicks((long)deltaTicks);
                NTPClient.SetTime(currCorrectWindowsTime);
            }

            double x, y, z;
            return NTPTimeKeeper.UtcNowNoDriftCorrection(out x, out y, out z);
        }