1689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org#!/usr/bin/env python 2689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org# Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org# 4689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org# Use of this source code is governed by a BSD-style license 5689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org# that can be found in the LICENSE file in the root of the source 6689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org# tree. An additional intellectual property rights grant can be found 7689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org# in the file PATENTS. All contributing project authors may 8689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org# be found in the AUTHORS file in the root of the source tree. 9689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org 10689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org__author__ = 'kjellander@webrtc.org (Henrik Kjellander)' 11689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org 12689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.orgclass DataHelper(object): 13689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org """ 14689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org Helper class for managing table data. 15689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org This class does not verify the consistency of the data tables sent into it. 16689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org """ 17689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org 18689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org def __init__(self, data_list, table_description, names_list, messages): 19689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org """ Initializes the DataHelper with data. 205d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org 21689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org Args: 225d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org data_list: List of one or more data lists in the format that the 23689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org Google Visualization Python API expects (list of dictionaries, one 245d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org per row of data). See the gviz_api.DataTable documentation for more 25689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org info. 26689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org table_description: dictionary describing the data types of all 27689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org columns in the data lists, as defined in the gviz_api.DataTable 28689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org documentation. 29689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org names_list: List of strings of what we're going to name the data 305d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org columns after. Usually different runs of data collection. 31689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org messages: List of strings we might append error messages to. 32689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org """ 33689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org self.data_list = data_list 34689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org self.table_description = table_description 35689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org self.names_list = names_list 36689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org self.messages = messages 37689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org self.number_of_datasets = len(data_list) 38689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org self.number_of_frames = len(data_list[0]) 395d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org 40689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org def CreateData(self, field_name, start_frame=0, end_frame=0): 41689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org """ Creates a data structure for a specified data field. 425d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org 435d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org Creates a data structure (data type description dictionary and a list 445d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org of data dictionaries) to be used with the Google Visualization Python 45689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org API. The frame_number column is always present and one column per data 465d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org set is added and its field name is suffixed by _N where N is the number 47689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org of the data set (0, 1, 2...) 485d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org 49689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org Args: 50689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org field_name: String name of the field, must be present in the data 51689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org structure this DataHelper was created with. 52689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org start_frame: Frame number to start at (zero indexed). Default: 0. 535d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org end_frame: Frame number to be the last frame. If zero all frames 54689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org will be included. Default: 0. 555d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org 56689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org Returns: 57689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org A tuple containing: 58689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org - a dictionary describing the columns in the data result_data_table below. 595d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org This description uses the name for each data set specified by 605d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org names_list. 615d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org 62689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org Example with two data sets named 'Foreman' and 'Crew': 63689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org { 64689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org 'frame_number': ('number', 'Frame number'), 65689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org 'ssim_0': ('number', 'Foreman'), 66689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org 'ssim_1': ('number', 'Crew'), 67689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org } 68689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org - a list containing dictionaries (one per row) with the frame_number 695d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org column and one column of the specified field_name column per data 705d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org set. 715d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org 72689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org Example with two data sets named 'Foreman' and 'Crew': 73689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org [ 74689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org {'frame_number': 0, 'ssim_0': 0.98, 'ssim_1': 0.77 }, 75689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org {'frame_number': 1, 'ssim_0': 0.81, 'ssim_1': 0.53 }, 76689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org ] 77689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org """ 785d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org 79689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org # Build dictionary that describes the data types 805d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org result_table_description = {'frame_number': ('string', 'Frame number')} 81689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org for dataset_index in range(self.number_of_datasets): 82689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org column_name = '%s_%s' % (field_name, dataset_index) 83689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org column_type = self.table_description[field_name][0] 84689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org column_description = self.names_list[dataset_index] 85689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org result_table_description[column_name] = (column_type, column_description) 86689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org 875d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org # Build data table of all the data 88689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org result_data_table = [] 895d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org # We're going to have one dictionary per row. 90689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org # Create that and copy frame_number values from the first data set 91689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org for source_row in self.data_list[0]: 9257e5fd2e604ff7e60425c3f7654b40da03fc763cHenrik Kjellander row_dict = {'frame_number': source_row['frame_number']} 93689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org result_data_table.append(row_dict) 945d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org 95689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org # Pick target field data points from the all data tables 96689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org if end_frame == 0: # Default to all frames 97689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org end_frame = self.number_of_frames 985d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org 99689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org for dataset_index in range(self.number_of_datasets): 100689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org for row_number in range(start_frame, end_frame): 101689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org column_name = '%s_%s' % (field_name, dataset_index) 102689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org # Stop if any of the data sets are missing the frame 103689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org try: 104689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org result_data_table[row_number][column_name] = \ 105689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org self.data_list[dataset_index][row_number][field_name] 106689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org except IndexError: 107689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org self.messages.append("Couldn't find frame data for row %d " 1085d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org "for %s" % (row_number, self.names_list[dataset_index])) 109689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org break 110418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org return result_table_description, result_data_table 111689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org 1125d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org def GetOrdering(self, table_description): # pylint: disable=R0201 113689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org """ Creates a list of column names, ordered alphabetically except for the 114689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org frame_number column which always will be the first column. 1155d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org 116689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org Args: 117689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org table_description: A dictionary of column definitions as defined by the 118689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org gviz_api.DataTable documentation. 119689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org Returns: 120689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org A list of column names, where frame_number is the first and the 121689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org remaining columns are sorted alphabetically. 122689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org """ 123689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org # The JSON data representation generated from gviz_api.DataTable.ToJSon() 1245d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org # must have frame_number as its first column in order for the chart to 125689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org # use it as it's X-axis value series. 1265d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org # gviz_api.DataTable orders the columns by name by default, which will 127689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org # be incorrect if we have column names that are sorted before frame_number 128689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org # in our data table. 129689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org columns_ordering = ['frame_number'] 130689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org # add all other columns: 131689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org for column in sorted(table_description.keys()): 132689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org if column != 'frame_number': 133689cb300b5050f771a77fb1808b1af8fdd6144d3kjellander@webrtc.org columns_ordering.append(column) 134418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org return columns_ordering 1355d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org 1365d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org def CreateConfigurationTable(self, configurations): # pylint: disable=R0201 137418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org """ Combines multiple test data configurations for display. 138418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org 139418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org Args: 140418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org configurations: List of one ore more configurations. Each configuration 141418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org is required to be a list of dictionaries with two keys: 'name' and 142418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org 'value'. 143418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org Example of a single configuration: 144418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org [ 145418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org {'name': 'name', 'value': 'VP8 software'}, 146418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org {'name': 'test_number', 'value': '0'}, 147418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org {'name': 'input_filename', 'value': 'foreman_cif.yuv'}, 148418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org ] 149418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org Returns: 150418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org A tuple containing: 151418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org - a dictionary describing the columns in the configuration table to be 152418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org displayed. All columns will have string as data type. 153418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org Example: 154418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org { 155418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org 'name': 'string', 156418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org 'test_number': 'string', 157418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org 'input_filename': 'string', 158418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org } 159418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org - a list containing dictionaries (one per configuration) with the 160418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org configuration column names mapped to the value for each test run: 161418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org 162418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org Example matching the columns above: 163418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org [ 164418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org {'name': 'VP8 software', 165418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org 'test_number': '12', 166418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org 'input_filename': 'foreman_cif.yuv' }, 167418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org {'name': 'VP8 hardware', 168418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org 'test_number': '5', 169418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org 'input_filename': 'foreman_cif.yuv' }, 170418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org ] 171418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org """ 172418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org result_description = {} 173418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org result_data = [] 174418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org 175418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org for configuration in configurations: 176418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org data = {} 177418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org result_data.append(data) 1785d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org for values in configuration: 1795d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org name = values['name'] 1805d37139374178479c16956a2a4eefd231206c2a1phoglund@webrtc.org value = values['value'] 181418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org result_description[name] = 'string' 182418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org data[name] = value 183418bce5ccceaee666e0f6142f23a858a35a98df7kjellander@webrtc.org return result_description, result_data 184