public HypothesisTest GetHypothesisTestResult() { // We are comparing the mean of sample means for a significant difference between the distributions // H0: there is no difference in the distribution of packets between marked and unmarked batches // H1: there is a difference between the batches /******************************************************************************************* * * Note: we need a test to verify that the following data (DisplayStatistic) has been updated * *******************************************************************************************/ HypothesisTest ht = new HypothesisTest(); //// Update the K-S statistics object //_KsStatistics.MarkedMean = markedMeanOfMeans; //_KsStatistics.MarkedStdDev = markedStdDevMeanOfMeans; ////_KsStatistics.MarkedMean = markedCumulativeStats.PacketCountMean; ////_KsStatistics.MarkedStdDev = markedCumulativeStats.PacketCountStandardDeviation; //_KsStatistics.MarkedIntervalCount = TrimIntervals == true ? markedCumulativeStats.IntervalCountTrimmed : markedCumulativeStats.IntervalCount; //_KsStatistics.UnmarkedMean = unmarkedMeanOfMeans; //_KsStatistics.UnmarkedStdDev = unmarkedStdDevMeanOfMeans; ////_KsStatistics.UnmarkedMean = unmarkedCumulativeStats.PacketCountMean; ////_KsStatistics.UnmarkedStdDev = unmarkedCumulativeStats.PacketCountStandardDeviation; //_KsStatistics.UnmarkedIntervalCount = TrimIntervals == true ? unmarkedCumulativeStats.IntervalCountTrimmed : unmarkedCumulativeStats.IntervalCount; ProcessCapturePackets pcp = new ProcessCapturePackets(); DisplayStatistic markedStatistics = new DisplayStatistic(); DisplayStatistic unmarkedStatistics = new DisplayStatistic(); markedStatistics = pcp.GetCumulativeMarkedDisplayStatistics(); unmarkedStatistics = pcp.GetCumulativeUnmarkedDisplayStatistics(); MeansTestStatistic _MeansTestStatistic = new MeansTestStatistic(AnalysisConfiguration.Alpha, AnalysisConfiguration.Zvalue); if (markedStatistics != null) { _MeansTestStatistic.MarkedMean = markedStatistics.MeanOfMeans; _MeansTestStatistic.MarkedStdDev = markedStatistics.MeanOfMeansStandardDeviation; _MeansTestStatistic.MarkedIntervalCount = _TrimZeroPacketIntervals == true ? markedStatistics.TrimmedIntervalCount : markedStatistics.IntervalCount; } if (unmarkedStatistics != null) { _MeansTestStatistic.UnmarkedMean = unmarkedStatistics.MeanOfMeans; _MeansTestStatistic.UnmarkedStdDev = unmarkedStatistics.MeanOfMeansStandardDeviation; _MeansTestStatistic.UnmarkedIntervalCount = _TrimZeroPacketIntervals == true ? unmarkedStatistics.TrimmedIntervalCount : unmarkedStatistics.IntervalCount; } // Test the difference in the distribution means decimal meanDifference = _MeansTestStatistic.MeanDifference; decimal sigmaDifference = _MeansTestStatistic.SigmaDifference; // Single-tail test (if there is a difference in the means it will be a positive value) // Z value for alpha = 5% significance level: // Test result: true = reject H0 - difference of means has only 5% probability of occurring if H0 is true // Note: standard deviation = SigmaDifference * Zvalue ht.MeansTestResult = _MeansTestStatistic.MeanDifference > _MeansTestStatistic.StandardDeviation ? true : false; ht.MeansVarianceStandardDeviation = _MeansTestStatistic.StandardDeviation; ht.MeanOfMeansVariance = _MeansTestStatistic.MeanDifference; return ht; }
public void CalculateHypothesisTestResults() { // Only perform these calculations if files have been processed and a pair of files (marked and unmarked) are available bool IsDirty = false; bool HasValues = false; HypothesisTest ht = new HypothesisTest(); ProcessCapturePackets pcp = new ProcessCapturePackets(); int markedFileCount = pcp.GetProcessedFilesCountMarked(); int unmarkedFileCount = pcp.GetProcessedFilesCountUnmarked(); ht = pcp.GetHypothesisTestResults(); if (ht != null) { HasValues = ht.HasValues; } //if (markedFileCount >= 1 && unmarkedFileCount >= 1 && (markedFileCount + unmarkedFileCount) % 2 == 0) if (markedFileCount >= 1 && unmarkedFileCount >= 1) { // Get mean of means test results HypothesisTest htMeans = new HypothesisTest(); //htMeans = GetMeansHypothesisTestResult(); MeansHypothesisTest mht = new MeansHypothesisTest(_TrimZeroPacketIntervals); htMeans = mht.GetHypothesisTestResult(); ht.MeansTestResult = htMeans.MeansTestResult; ht.MeanOfMeansVariance = htMeans.MeanOfMeansVariance; ht.MeansVarianceStandardDeviation = htMeans.MeansVarianceStandardDeviation; if(AnalysisConfiguration.HypothesisTestType == HypothesisTestType.MeansTest && htMeans.MeansTestResult) { AnalysisConfiguration.FoundCoresidentVm = true; } else { AnalysisConfiguration.FoundCoresidentVm = false; } if (AnalysisConfiguration.HypothesisTestType == HypothesisTestType.KsTestStep) { // Get the K-S test results (using step function between probability data points) HypothesisTest htKsStep = new HypothesisTest(); //htKsStep = GetKsStepHypothesisTestResult(); KsStepHypothesisTest ksht = new KsStepHypothesisTest(); htKsStep = ksht.GetHypothesisTestResult(); ht.KsStatistic = htKsStep.KsStatistic; ht.MaxCpdVariance = htKsStep.MaxCpdVariance; ht.KsTestResult = htKsStep.KsTestResult; ht.HasValues = true; IsDirty = true; if(htKsStep.KsTestResult) { AnalysisConfiguration.FoundCoresidentVm = true; } else { AnalysisConfiguration.FoundCoresidentVm = false; } } //else else if(AnalysisConfiguration.HypothesisTestType == HypothesisTestType.KsTestLinear) { // Default: Get the K-S test results (using linear extrapolation between probability data points) HypothesisTest htKsLinear = new HypothesisTest(); //htKsLinear = GetKsLinearHypothesisTestResult(); KsLinearHypothesisTest klht = new KsLinearHypothesisTest(); htKsLinear = klht.GetHypothesisTestResult(); ht.KsStatistic = htKsLinear.KsStatistic; ht.MaxCpdVariance = htKsLinear.MaxCpdVariance; ht.KsTestResult = htKsLinear.KsTestResult; ht.HasValues = true; IsDirty = true; if (htKsLinear.KsTestResult) { AnalysisConfiguration.FoundCoresidentVm = true; } else { AnalysisConfiguration.FoundCoresidentVm = false; } } } else if(!HasValues) { // Default values - only if we haven't previously calculated hypothesis test results ht.MeanOfMeansVariance = 0; ht.MeansVarianceStandardDeviation = 0; ht.MeansTestResult = false; ht.KsTestResult = false; ht.HasValues = false; IsDirty = true; } if (IsDirty) { // Save the test results pcp.DeleteHypothesisTestResults(); pcp.InsertHypothesisTestResults(ht); } }
private void RefreshKsStatistics() { // Reset the backcolor for Reject H0? cell in K-S column of grid _AnalysisDataGridView.Rows[8].Cells[7].Style.BackColor = Color.White; //bool KS_result = GetHypothesisTestResult(_KsStatistics.UnmarkedMean, _KsStatistics.MarkedMean, _KsStatistics.UnmarkedStdDev, _KsStatistics.MarkedStdDev, _KsStatistics.UnmarkedIntervalCount, _KsStatistics.MarkedIntervalCount); //bool KS_result = GetHypothesisTestResult(_KsStatistics.UnmarkedMean, _KsStatistics.MarkedMean, _KsStatistics.UnmarkedStdDev, _KsStatistics.MarkedStdDev, _KsStatistics.UnmarkedIntervalCount, _KsStatistics.MarkedIntervalCount); ProcessCapturePackets pcp = new ProcessCapturePackets(); HypothesisTest ht = new HypothesisTest(); ht = pcp.GetHypothesisTestResults(); int row = 0; _AnalysisDataGridView.Rows[row++].Cells[7].Value = "N/A"; _AnalysisDataGridView.Rows[row++].Cells[7].Value = "N/A"; _AnalysisDataGridView.Rows[row++].Cells[7].Value = "N/A"; _AnalysisDataGridView.Rows[row++].Cells[7].Value = string.Format("{0:N2}", ht.MaxCpdVariance); _AnalysisDataGridView.Rows[row++].Cells[7].Value = "N/A"; _AnalysisDataGridView.Rows[row++].Cells[7].Value = "N/A"; _AnalysisDataGridView.Rows[row++].Cells[7].Value = string.Format("{0:N2}", ht.KsStatistic); _AnalysisDataGridView.Rows[row++].Cells[7].Value = string.Format("{0:P1}", AnalysisConfiguration.Alpha); Font font = new Font(_AnalysisDataGridView.DefaultCellStyle.Font.FontFamily, _AnalysisDataGridView.Font.Size, FontStyle.Bold); _AnalysisDataGridView.Rows[row].Cells[7].Style.Font = font; _AnalysisDataGridView.Rows[row].Cells[7].Value = ht.KsTestResult.ToString(); _AnalysisDataGridView.Rows[row].Cells[7].Style.BackColor = ht.KsTestResult == true ? Color.LightGreen : Color.LightCoral; }
private void RefreshCumulativeBatchStatistics() { // Get the cumulative interval counts ProcessCapturePackets pcp = new ProcessCapturePackets(); //BindingList<CumulativeInterval> cumulativeIntervals = new BindingList<CumulativeInterval>(); //cumulativeIntervals = pcp.GetCumulativeIntervals(); //// Get the batch intervals //BindingList<BatchIntervalMarked> unmarkedBatchIntervals = new BindingList<BatchIntervalMarked>(); //BindingList<BatchIntervalMarked> markedBatchIntervals = new BindingList<BatchIntervalMarked>(); //foreach (CumulativeInterval ci in cumulativeIntervals) //{ // if (ci.Marked) // { // BatchIntervalMarked bim = new BatchIntervalMarked(); // bim.BatchIntervalId = 0; // bim.CaptureBatchId = 0; // bim.IntervalNumber = ci.CumulativeIntervalNumber; // bim.Marked = CaptureState.Marked; // bim.PacketCount = ci.PacketCount; // markedBatchIntervals.Add(bim); // } // else // { // BatchIntervalMarked bim = new BatchIntervalMarked(); // bim.BatchIntervalId = 0; // bim.CaptureBatchId = 0; // bim.IntervalNumber = ci.CumulativeIntervalNumber; // bim.Marked = CaptureState.Unmarked; // bim.PacketCount = ci.PacketCount; // unmarkedBatchIntervals.Add(bim); // } //} //BatchStatistics markedCumulativeStats = new BatchStatistics(); //BatchStatistics unmarkedCumulativeStats = new BatchStatistics(); //decimal markedMeanOfMeans = 0; //decimal markedStdDevMeanOfMeans = 0; //decimal unmarkedMeanOfMeans = 0; //decimal unmarkedStdDevMeanOfMeans = 0; //AnalysisEngine ae = new AnalysisEngine(); // Get the marked cumulative statistics DisplayStatistic markedCumulativeStats = new DisplayStatistic(); markedCumulativeStats = pcp.GetCumulativeMarkedDisplayStatistics(); if (markedCumulativeStats != null) { //if(markedBatchIntervals.Count > 0) //{ // markedCumulativeStats = ae.CalculateBatchStatistics(markedBatchIntervals,CaptureState.Marked, BatchType.Cumulative); // markedMeanOfMeans = pcp.CalculateMeanOfMeans(CaptureState.Marked, TrimIntervals ? true : false); // markedStdDevMeanOfMeans = pcp.CalculateStdDevForMeanOfMeans(CaptureState.Marked, TrimIntervals ? true : false); // Load up the table // Cumulative marked column int row = 0; _AnalysisDataGridView.Rows[row++].Cells[5].Value = markedCumulativeStats.IntervalCount; _AnalysisDataGridView.Rows[row++].Cells[5].Value = TrimIntervals == true ? markedCumulativeStats.TrimmedIntervalCount.ToString() : "N/A"; _AnalysisDataGridView.Rows[row++].Cells[5].Value = string.Format("{0:N2}", markedCumulativeStats.MeanPacketsPerInterval); _AnalysisDataGridView.Rows[row++].Cells[5].Value = string.Format("{0:N2}", markedCumulativeStats.StandardDeviation); _AnalysisDataGridView.Rows[row++].Cells[5].Value = markedCumulativeStats.MinPacketsPerInterval; _AnalysisDataGridView.Rows[row++].Cells[5].Value = markedCumulativeStats.MaxPacketsPerInterval; _AnalysisDataGridView.Rows[row++].Cells[5].Value = string.Format("{0:N2}", markedCumulativeStats.MeanOfMeans); _AnalysisDataGridView.Rows[row++].Cells[5].Value = "N/A"; _AnalysisDataGridView.Rows[row++].Cells[5].Value = "N/A"; //} } // Get the marked cumulative statistics DisplayStatistic unmarkedCumulativeStats = new DisplayStatistic(); unmarkedCumulativeStats = pcp.GetCumulativeUnmarkedDisplayStatistics(); if (unmarkedCumulativeStats != null) { //if (unmarkedBatchIntervals.Count > 0) //{ // unmarkedCumulativeStats = ae.CalculateBatchStatistics(unmarkedBatchIntervals, CaptureState.Marked, BatchType.Cumulative); // unmarkedMeanOfMeans = pcp.CalculateMeanOfMeans(CaptureState.Unmarked, TrimIntervals ? true : false); // unmarkedStdDevMeanOfMeans = pcp.CalculateStdDevForMeanOfMeans(CaptureState.Unmarked, TrimIntervals ? true : false); // Load up the table // Cumulative unmarked column int row = 0; _AnalysisDataGridView.Rows[row++].Cells[4].Value = unmarkedCumulativeStats.IntervalCount; _AnalysisDataGridView.Rows[row++].Cells[4].Value = TrimIntervals == true ? unmarkedCumulativeStats.TrimmedIntervalCount.ToString() : "N/A"; _AnalysisDataGridView.Rows[row++].Cells[4].Value = string.Format("{0:N2}", unmarkedCumulativeStats.MeanPacketsPerInterval); _AnalysisDataGridView.Rows[row++].Cells[4].Value = string.Format("{0:N2}", unmarkedCumulativeStats.StandardDeviation); _AnalysisDataGridView.Rows[row++].Cells[4].Value = unmarkedCumulativeStats.MinPacketsPerInterval; _AnalysisDataGridView.Rows[row++].Cells[4].Value = unmarkedCumulativeStats.MaxPacketsPerInterval; _AnalysisDataGridView.Rows[row++].Cells[4].Value = string.Format("{0:N2}", unmarkedCumulativeStats.MeanOfMeans); _AnalysisDataGridView.Rows[row++].Cells[4].Value = "N/A"; _AnalysisDataGridView.Rows[row++].Cells[4].Value = "N/A"; //} } //if (markedBatchIntervals.Count > 0 && unmarkedBatchIntervals.Count > 0) if (markedCumulativeStats != null && unmarkedCumulativeStats != null) { // Get the Hypothesis Test results HypothesisTest ht = new HypothesisTest(); ht = pcp.GetHypothesisTestResults(); // Specify font for hypothesis test result fields Font font = new Font(_AnalysisDataGridView.DefaultCellStyle.Font.FontFamily, _AnalysisDataGridView.Font.Size, FontStyle.Bold); // Cumulative variance column int row = 0; _AnalysisDataGridView.Rows[row++].Cells[6].Value = unmarkedCumulativeStats.IntervalCount - markedCumulativeStats.IntervalCount; _AnalysisDataGridView.Rows[row++].Cells[6].Value = TrimIntervals == true ? (unmarkedCumulativeStats.TrimmedIntervalCount - markedCumulativeStats.TrimmedIntervalCount).ToString() : "N/A"; _AnalysisDataGridView.Rows[row++].Cells[6].Value = string.Format("{0:N2}", (unmarkedCumulativeStats.MeanPacketsPerInterval - markedCumulativeStats.MeanPacketsPerInterval)); _AnalysisDataGridView.Rows[row++].Cells[6].Value = string.Format("{0:N2}", (unmarkedCumulativeStats.StandardDeviation - markedCumulativeStats.StandardDeviation)); _AnalysisDataGridView.Rows[row++].Cells[6].Value = unmarkedCumulativeStats.MinPacketsPerInterval - markedCumulativeStats.MinPacketsPerInterval; _AnalysisDataGridView.Rows[row++].Cells[6].Value = unmarkedCumulativeStats.MaxPacketsPerInterval - markedCumulativeStats.MaxPacketsPerInterval; _AnalysisDataGridView.Rows[row++].Cells[6].Value = string.Format("{0:N2}", (unmarkedCumulativeStats.MeanOfMeans - markedCumulativeStats.MeanOfMeans)); _AnalysisDataGridView.Rows[row++].Cells[6].Value = string.Format("{0:P1}", AnalysisConfiguration.Alpha); // Means test results _AnalysisDataGridView.Rows[row].Cells[6].Style.Font = font; _AnalysisDataGridView.Rows[row].Cells[6].Value = ht.MeansTestResult == true ? "True" : "False"; _AnalysisDataGridView.Rows[row].Cells[6].Style.BackColor = ht.MeansTestResult == true ? Color.LightGreen : Color.LightCoral; //// Update the K-S statistics column //row = 0; //_AnalysisDataGridView.Rows[row++].Cells[7].Value = "N/A"; //_AnalysisDataGridView.Rows[row++].Cells[7].Value = "N/A"; //_AnalysisDataGridView.Rows[row++].Cells[7].Value = "N/A"; //_AnalysisDataGridView.Rows[row++].Cells[7].Value = string.Format("{0:N2}", ht.MeansVarianceStandardDeviation); //_AnalysisDataGridView.Rows[row++].Cells[7].Value = "N/A"; //_AnalysisDataGridView.Rows[row++].Cells[7].Value = "N/A"; //_AnalysisDataGridView.Rows[row++].Cells[7].Value = string.Format("{0:N2}", ht.MeanOfMeansVariance); //_AnalysisDataGridView.Rows[row++].Cells[7].Value = string.Format("{0:P1}", AnalysisConfiguration.Alpha); //// K-S test results //_AnalysisDataGridView.Rows[row].Cells[7].Style.Font = font; //_AnalysisDataGridView.Rows[row].Cells[7].Value = ht.KsTestResult == true ? "True" : "False"; //_AnalysisDataGridView.Rows[row].Cells[7].Style.BackColor = ht.KsTestResult == true ? Color.LightGreen : Color.LightCoral; } //// Update the K-S statistics object //_KsStatistics.MarkedMean = markedMeanOfMeans; //_KsStatistics.MarkedStdDev = markedStdDevMeanOfMeans; ////_KsStatistics.MarkedMean = markedCumulativeStats.PacketCountMean; ////_KsStatistics.MarkedStdDev = markedCumulativeStats.PacketCountStandardDeviation; //_KsStatistics.MarkedIntervalCount = TrimIntervals == true ? markedCumulativeStats.IntervalCountTrimmed : markedCumulativeStats.IntervalCount; //_KsStatistics.UnmarkedMean = unmarkedMeanOfMeans; //_KsStatistics.UnmarkedStdDev = unmarkedStdDevMeanOfMeans; ////_KsStatistics.UnmarkedMean = unmarkedCumulativeStats.PacketCountMean; ////_KsStatistics.UnmarkedStdDev = unmarkedCumulativeStats.PacketCountStandardDeviation; //_KsStatistics.UnmarkedIntervalCount = TrimIntervals == true ? unmarkedCumulativeStats.IntervalCountTrimmed : unmarkedCumulativeStats.IntervalCount; }
public void InsertHypothesisTestResults(HypothesisTest testResults) { DisplayStatisticsData dsd = new DisplayStatisticsData(); dsd.InsertHypothesisTestResults(testResults); }
public HypothesisTest GetHypothesisTestResults() { HypothesisTest ht = new HypothesisTest(); DisplayStatisticsData dsd = new DisplayStatisticsData(); ht = dsd.GetHypothesisTestResults(); if (ht != null) { return ht; } else { return new HypothesisTest(); } }
public void InsertHypothesisTestResults(HypothesisTest testResults) { using (var context = new PacketAnalysisEntity()) { context.HypothesisTests.Add(testResults); context.SaveChanges(); } }
public HypothesisTest GetHypothesisTestResults() { HypothesisTest ht = new HypothesisTest(); using (var context = new PacketAnalysisEntity()) { var testResults = (from t in context.HypothesisTests select t).FirstOrDefault(); ht = testResults as HypothesisTest; } return ht; }
public HypothesisTest GetHypothesisTestResult() { HypothesisTest ht = new HypothesisTest(); ; // Get cumulative probability distribution data and find the max difference between marked and unmarked distributions ProcessCapturePackets pcp = new ProcessCapturePackets(); BindingList<CumulativeProbabilityDistribution> markedCPD = new BindingList<CumulativeProbabilityDistribution>(); BindingList<CumulativeProbabilityDistribution> unmarkedCPD = new BindingList<CumulativeProbabilityDistribution>(); markedCPD = pcp.GetCumulativeProbabilityDistributionData(CaptureState.Marked); unmarkedCPD = pcp.GetCumulativeProbabilityDistributionData(CaptureState.Unmarked); if (markedCPD.Count > 0 && unmarkedCPD.Count > 0) { decimal maxVariance = 0M; int intervalCount = 0; // Only compare intervals from each distribution with a corresponding interval in the other distribution if (unmarkedCPD.Count > markedCPD.Count) { intervalCount = markedCPD.Count; } else { intervalCount = unmarkedCPD.Count; } // Expand each distribution into equal discrete steps for comparison of cumulative probabilities // First, find the largest cumulative packet count (= interval) int maxPacketCount = 0; if (markedCPD[markedCPD.Count - 1].Interval >= unmarkedCPD[unmarkedCPD.Count - 1].Interval) { maxPacketCount = markedCPD[markedCPD.Count - 1].Interval; } else { maxPacketCount = unmarkedCPD[unmarkedCPD.Count - 1].Interval; } // Second, expand the packet counts by interpolating between packet counts (intervals) using an average probability // for each packet count in the range and successively adding up to the next packet count (interval); add these // interpolated packets to a dictionary; outcome is a dictionary for each distribution containing packet counts and // probabilities from packet count = 0 to packet count = largest packet count (interval) of both distributions and // the associated probabilities for each packet count. We are basically calculating a linear estimate of packet // counts and probabilities between each packet count and probability in the actual distributions. //// Third, check for packet counts that are less than the maximum packet count and assign a probability of 1 //// to any that are found ExpandPacketCountLinear markedExpPktCount = new ExpandPacketCountLinear(markedCPD, maxPacketCount); ExpandPacketCountLinear unmarkedExpPktCount = new ExpandPacketCountLinear(unmarkedCPD, maxPacketCount); SortedDictionary<int, decimal> markedCPDExpanded = new SortedDictionary<int, decimal>(); SortedDictionary<int, decimal> unmarkedCPDExpanded = new SortedDictionary<int, decimal>(); //markedCPDExpanded = ExpandPacketCount(markedCPD, maxPacketCount); //unmarkedCPDExpanded = ExpandPacketCount(unmarkedCPD, maxPacketCount); markedCPDExpanded = markedExpPktCount.ExpandPacketCount(); unmarkedCPDExpanded = unmarkedExpPktCount.ExpandPacketCount(); // Find the maximum variance between the cumulative probabilities in each distribution for (int i = 0; i < maxPacketCount; i++) { #region Debug #if(DEBUG) System.Diagnostics.Debug.WriteLine("unmarkedCPDExpanded[{0}]:[{1}] - markedCPDExpanded[{2}]:[{3}] = {4}", i, unmarkedCPDExpanded[i], i, markedCPDExpanded[i], Math.Abs(unmarkedCPDExpanded[i] - markedCPDExpanded[i])); #endif #endregion if (Math.Abs(unmarkedCPDExpanded[i] - markedCPDExpanded[i]) > maxVariance) { maxVariance = Math.Abs(unmarkedCPDExpanded[i] - markedCPDExpanded[i]); } } // Multiply by the square root of the sample size factor maxVariance = maxVariance * Convert.ToDecimal(Math.Sqrt((markedCPD.Count * unmarkedCPD.Count) / (markedCPD.Count + unmarkedCPD.Count))); // Compare the maximum variance with the hypothesis test threshold // For significance level alpha = 0.05, the K-S statistic is computed as 1.36/N^(1/2), where N is the number of samples decimal ksStatistic = Convert.ToDecimal(1.36 / Math.Pow(intervalCount, 0.5)); ht.KsStatistic = ksStatistic; ht.MaxCpdVariance = maxVariance; if (maxVariance > ksStatistic) { // Reject the null hypothesis ht.KsTestResult = true; } } else { // Not enough data to perform the test ht.KsStatistic = 0; ht.MaxCpdVariance = 0; ht.KsTestResult = false; } return ht; }