/**
 * InsertChart adds a chart for the given $metric, with the given $label, to
 * global $chartData, and outputs the HTML container elements for the chart.
 *
 * @param string $metric Metric to add
 * @param string $label Label corresponding to metric
 */
function InsertChart($metric, $label)
{
    global $chartData;
    global $num_runs;
    // @var integer Number of runs
    global $views;
    global $colors;
    global $light_colors;
    global $median_metric;
    global $pagesData;
    global $testsInfo;
    global $testsId;
    global $testsLabel;
    global $median_value;
    global $median_run;
    global $statControl;
    $num_runs = max(array_map("numRunsFromTestInfo", $testsInfo));
    // Write HTML for chart
    $div = "{$metric}Chart";
    echo "<h2 id=\"{$metric}\">" . htmlspecialchars($label) . "</h2>";
    if (!$testsInfo) {
        return;
    }
    $chartColumns = array(ChartColumn::runs($num_runs));
    $compareTable = array();
    $view_index = 0;
    // For each view (first / repeat) that we want to show
    foreach ($views as $cached) {
        $statValues = array();
        $statLabels = array();
        // For each run in that view
        foreach ($pagesData as $key => $pageData) {
            // Construct label from those descriptive attributes that are not
            // common to all variants.
            $labels = array();
            if (count($pagesData) > 1) {
                $labels[] = $testsLabel[$key];
            }
            if (count($views) > 1) {
                $labels[] = $cached == '1' ? 'Repeat View' : 'First View';
            }
            // Prepare Chart object and add to $chartData for later chart construction.
            // If $view_index is greater than the number of colors, we will pass NULL
            // as a color, which will lead to GViz choosing a color.
            $chartColumnsAdd = ChartColumn::dataMedianColumns($pageData, $cached, $metric, $median_metric, $colors[$view_index], $light_colors[$view_index], $labels, $num_runs, $median_run, $median_value);
            $chartColumns = array_merge($chartColumns, $chartColumnsAdd);
            $view_index++;
            // If doing a statistical comparison, prepare raw values and labels.
            if ($statControl !== 'NOSTAT' && count($pagesData) >= 1) {
                $statValues[] = values($pageData, $cached, $metric, true);
                $statLabels[] = implode(" ", $labels);
            }
        }
        if ($statControl !== 'NOSTAT' && count($pagesData) >= 1) {
            // First populate compareFrom for statistical control, if it has values
            if (count($statValues[$statControl]) > 0) {
                $statDiv = "{$metric}Stat{$cached}";
                $compareFrom = array();
                $confData = ConfData::fromArr($statLabels[$statControl], $statValues[$statControl]);
                $compareFrom[$statControl] = new CompareFrom($confData, NULL, NULL);
                foreach ($pagesData as $key => $pageData) {
                    // Skip the statistical control (we already handled it)
                    if ($key == $statControl) {
                        continue;
                    }
                    // Skip runs with missing values for the statistic.
                    if (count($statValues[$key]) == 0) {
                        continue;
                    }
                    // Populate compareFrom for $key
                    $confData = ConfData::fromArr($statLabels[$key], $statValues[$key]);
                    $pValue = \PHPStats\StatisticalTests::twoSampleTTest($statValues[$statControl], $statValues[$key]);
                    $diff = $confData->mean - $compareFrom[$statControl]->confData->mean;
                    // Derive 2-tailed p-value from 1-tailed p-view returned by twoSampleTTest.
                    $pValue = $diff > 0 ? 2 * $pValue : 2 * (1 - $pValue);
                    $compareFrom[$key] = new CompareFrom($confData, $diff, $pValue);
                }
                $compareTable[] = new CompareTable($statDiv, $compareFrom);
                echo "<div id=\"{$statDiv}\"></div>\n";
            }
        }
    }
    $chart = new Chart($div, $chartColumns, $compareTable);
    $chartData[$metric] = $chart;
    echo "<div id=\"{$div}\" class=\"chart\"></div>\n";
}
예제 #2
0
/**
 * InsertChart adds a chart for the given $metric, with the given $label, to
 * global $chartData, and outputs the HTML container elements for the chart.
 *
 * @param string $metric Metric to add
 * @param string $label Label corresponding to metric
 */
function InsertChart($metric, $label)
{
    global $chartData;
    global $num_runs;
    // @var integer Number of runs
    global $views;
    global $colors;
    global $light_colors;
    global $median_metric;
    global $pagesData;
    global $testsInfo;
    global $testsId;
    global $testsLabel;
    global $median_value;
    global $median_run;
    global $statControl;
    $num_runs = max(array_map("numRunsFromTestInfo", $testsInfo));
    // Write HTML for chart
    $div = "{$metric}Chart";
    echo "<h2 id=\"{$metric}\">" . htmlspecialchars($label) . "</h2>";
    if (!$testsInfo) {
        return;
    }
    $chartColumns = array(ChartColumn::runs($num_runs));
    $compareTable = array();
    $view_index = 0;
    if (count($pagesData) == 1 && $num_runs >= 3) {
        echo '<div class="chartStats"><table class="pretty">';
        echo '<tr><td></td><th>Mean</th><th>Median</th><th>p25</th><th>p75</th><th>p75-p25</th><th>StdDev</th><th>CV</th></tr>';
        foreach ($views as $cached) {
            $pageData = reset($pagesData);
            echo '<tr>';
            $label = $cached == '1' ? 'Repeat View' : 'First View';
            echo "<th style=\"text-align: right;\">{$label}</th>";
            $values = values($pageData, $cached, $metric, true);
            sort($values, SORT_NUMERIC);
            $sum = array_sum($values);
            $count = count($values);
            $mean = number_format($sum / $count, 3, '.', '');
            echo "<td>{$mean}</td>";
            $median = $values[intval($count / 2)];
            echo "<td>{$median}</td>";
            $p25 = $values[intval($count * 0.25)];
            echo "<td>{$p25}</td>";
            $p75 = $values[intval($count * 0.75)];
            echo "<td>{$p75}</td>";
            echo "<td>" . ($p75 - $p25) . "</td>";
            $sqsum = 0;
            foreach ($values as $value) {
                $sqsum += pow($value - $mean, 2);
            }
            $stddev = number_format(sqrt($sqsum / $count), 3, '.', '');
            echo "<td>{$stddev}</td>";
            echo "<td>" . number_format($stddev / $mean * 100, 3, '.', '') . "%</td>";
            echo '</tr>';
        }
        echo '</table></div>';
    }
    // For each view (first / repeat) that we want to show
    foreach ($views as $cached) {
        $statValues = array();
        $statLabels = array();
        // For each run in that view
        foreach ($pagesData as $key => $pageData) {
            // Construct label from those descriptive attributes that are not
            // common to all variants.
            $labels = array();
            if (count($pagesData) > 1) {
                $labels[] = $testsLabel[$key];
            }
            if (count($views) > 1) {
                $labels[] = $cached == '1' ? 'Repeat View' : 'First View';
            }
            // Prepare Chart object and add to $chartData for later chart construction.
            // If $view_index is greater than the number of colors, we will pass NULL
            // as a color, which will lead to GViz choosing a color.
            $chartColumnsAdd = ChartColumn::dataMedianColumns($pageData, $cached, $metric, $median_metric, $colors[$view_index], $light_colors[$view_index], $labels, $num_runs, $median_run, $median_value);
            $chartColumns = array_merge($chartColumns, $chartColumnsAdd);
            $view_index++;
            // If doing a statistical comparison, prepare raw values and labels.
            if ($statControl !== 'NOSTAT' && count($pagesData) >= 1) {
                $statValues[] = values($pageData, $cached, $metric, true);
                $statLabels[] = implode(" ", $labels);
            }
        }
        if (is_file('lib/PHPStats/PHPStats.phar') && $statControl !== 'NOSTAT' && count($pagesData) >= 1) {
            require_once 'lib/PHPStats/PHPStats.phar';
            require_once 'stat.inc';
            // First populate compareFrom for statistical control, if it has values
            if (count($statValues[$statControl]) > 0) {
                $statDiv = "{$metric}Stat{$cached}";
                $compareFrom = array();
                $confData = ConfData::fromArr($statLabels[$statControl], $statValues[$statControl]);
                $compareFrom[$statControl] = new CompareFrom($confData, NULL, NULL);
                foreach ($pagesData as $key => $pageData) {
                    // Skip the statistical control (we already handled it)
                    if ($key == $statControl) {
                        continue;
                    }
                    // Skip runs with missing values for the statistic.
                    if (count($statValues[$key]) == 0) {
                        continue;
                    }
                    // Populate compareFrom for $key
                    $confData = ConfData::fromArr($statLabels[$key], $statValues[$key]);
                    $pValue = \PHPStats\StatisticalTests::twoSampleTTest($statValues[$statControl], $statValues[$key]);
                    $diff = $confData->mean - $compareFrom[$statControl]->confData->mean;
                    // Derive 2-tailed p-value from 1-tailed p-view returned by twoSampleTTest.
                    $pValue = $diff > 0 ? 2 * $pValue : 2 * (1 - $pValue);
                    $compareFrom[$key] = new CompareFrom($confData, $diff, $pValue);
                }
                $compareTable[] = new CompareTable($statDiv, $compareFrom);
                echo "<div id=\"{$statDiv}\"></div>\n";
            }
        }
    }
    $chart = new Chart($div, $chartColumns, $compareTable);
    $chartData[$metric] = $chart;
    echo "<div id=\"{$div}\" class=\"chart\"></div>\n";
}