| OLD | NEW |
| 1 # Copyright 2013 The Chromium Authors. All rights reserved. | 1 # Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import numbers | 5 import numbers |
| 6 import math | 6 import math |
| 7 | 7 |
| 8 from telemetry import value as value_module | 8 from telemetry import value as value_module |
| 9 from telemetry.value import none_values | 9 from telemetry.value import none_values |
| 10 from telemetry.value import summarizable |
| 10 | 11 |
| 11 | 12 |
| 12 def Variance(sample): | 13 def Variance(sample): |
| 13 """ Compute the population variance. | 14 """ Compute the population variance. |
| 14 | 15 |
| 15 Args: | 16 Args: |
| 16 sample: a list of numbers. | 17 sample: a list of numbers. |
| 17 """ | 18 """ |
| 18 k = len(sample) - 1 # Bessel correction | 19 k = len(sample) - 1 # Bessel correction |
| 19 if k <= 0: | 20 if k <= 0: |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 total_degrees_of_freedom += k | 55 total_degrees_of_freedom += k |
| 55 if total_degrees_of_freedom: | 56 if total_degrees_of_freedom: |
| 56 return (pooled_variance/total_degrees_of_freedom) ** 0.5 | 57 return (pooled_variance/total_degrees_of_freedom) ** 0.5 |
| 57 return 0 | 58 return 0 |
| 58 | 59 |
| 59 | 60 |
| 60 def _Mean(values): | 61 def _Mean(values): |
| 61 return float(sum(values)) / len(values) if len(values) > 0 else 0.0 | 62 return float(sum(values)) / len(values) if len(values) > 0 else 0.0 |
| 62 | 63 |
| 63 | 64 |
| 64 class ListOfScalarValues(value_module.Value): | 65 class ListOfScalarValues(summarizable.SummarizableValue): |
| 65 """ ListOfScalarValues represents a list of numbers. | 66 """ ListOfScalarValues represents a list of numbers. |
| 66 | 67 |
| 67 By default, std is the standard deviation of all numbers in the list. Std can | 68 By default, std is the standard deviation of all numbers in the list. Std can |
| 68 also be specified in the constructor if the numbers are not from the same | 69 also be specified in the constructor if the numbers are not from the same |
| 69 population. | 70 population. |
| 70 """ | 71 """ |
| 71 def __init__(self, page, name, units, values, | 72 def __init__(self, page, name, units, values, |
| 72 important=True, description=None, | 73 important=True, description=None, |
| 73 tir_label=None, none_value_reason=None, | 74 tir_label=None, none_value_reason=None, |
| 74 std=None, same_page_merge_policy=value_module.CONCATENATE): | 75 std=None, same_page_merge_policy=value_module.CONCATENATE, |
| 76 improvement_direction=None): |
| 75 super(ListOfScalarValues, self).__init__(page, name, units, important, | 77 super(ListOfScalarValues, self).__init__(page, name, units, important, |
| 76 description, tir_label) | 78 description, tir_label, |
| 79 improvement_direction) |
| 77 if values is not None: | 80 if values is not None: |
| 78 assert isinstance(values, list) | 81 assert isinstance(values, list) |
| 79 assert len(values) > 0 | 82 assert len(values) > 0 |
| 80 assert all(isinstance(v, numbers.Number) for v in values) | 83 assert all(isinstance(v, numbers.Number) for v in values) |
| 81 assert std is None or isinstance(std, numbers.Number) | 84 assert std is None or isinstance(std, numbers.Number) |
| 82 else: | 85 else: |
| 83 assert std is None | 86 assert std is None |
| 84 none_values.ValidateNoneValueReason(values, none_value_reason) | 87 none_values.ValidateNoneValueReason(values, none_value_reason) |
| 85 self.values = values | 88 self.values = values |
| 86 self.none_value_reason = none_value_reason | 89 self.none_value_reason = none_value_reason |
| (...skipping 16 matching lines...) Expand all Loading... |
| 103 if self.page: | 106 if self.page: |
| 104 page_name = self.page.display_name | 107 page_name = self.page.display_name |
| 105 else: | 108 else: |
| 106 page_name = 'None' | 109 page_name = 'None' |
| 107 if self.same_page_merge_policy == value_module.CONCATENATE: | 110 if self.same_page_merge_policy == value_module.CONCATENATE: |
| 108 merge_policy = 'CONCATENATE' | 111 merge_policy = 'CONCATENATE' |
| 109 else: | 112 else: |
| 110 merge_policy = 'PICK_FIRST' | 113 merge_policy = 'PICK_FIRST' |
| 111 return ('ListOfScalarValues(%s, %s, %s, %s, ' | 114 return ('ListOfScalarValues(%s, %s, %s, %s, ' |
| 112 'important=%s, description=%s, tir_label=%s, ' | 115 'important=%s, description=%s, tir_label=%s, ' |
| 113 'same_page_merge_policy=%s)') % ( | 116 'same_page_merge_policy=%s, improvement_direction=%s)') % ( |
| 114 page_name, | 117 page_name, |
| 115 self.name, | 118 self.name, |
| 116 self.units, | 119 self.units, |
| 117 repr(self.values), | 120 repr(self.values), |
| 118 self.important, | 121 self.important, |
| 119 self.description, | 122 self.description, |
| 120 self.tir_label, | 123 self.tir_label, |
| 121 merge_policy) | 124 merge_policy, |
| 125 self.improvement_direction) |
| 122 | 126 |
| 123 def GetBuildbotDataType(self, output_context): | 127 def GetBuildbotDataType(self, output_context): |
| 124 if self._IsImportantGivenOutputIntent(output_context): | 128 if self._IsImportantGivenOutputIntent(output_context): |
| 125 return 'default' | 129 return 'default' |
| 126 return 'unimportant' | 130 return 'unimportant' |
| 127 | 131 |
| 128 def GetBuildbotValue(self): | 132 def GetBuildbotValue(self): |
| 129 return self.values | 133 return self.values |
| 130 | 134 |
| 131 def GetRepresentativeNumber(self): | 135 def GetRepresentativeNumber(self): |
| (...skipping 18 matching lines...) Expand all Loading... |
| 150 if self.none_value_reason is not None: | 154 if self.none_value_reason is not None: |
| 151 d['none_value_reason'] = self.none_value_reason | 155 d['none_value_reason'] = self.none_value_reason |
| 152 | 156 |
| 153 return d | 157 return d |
| 154 | 158 |
| 155 @staticmethod | 159 @staticmethod |
| 156 def FromDict(value_dict, page_dict): | 160 def FromDict(value_dict, page_dict): |
| 157 kwargs = value_module.Value.GetConstructorKwArgs(value_dict, page_dict) | 161 kwargs = value_module.Value.GetConstructorKwArgs(value_dict, page_dict) |
| 158 kwargs['values'] = value_dict['values'] | 162 kwargs['values'] = value_dict['values'] |
| 159 kwargs['std'] = value_dict['std'] | 163 kwargs['std'] = value_dict['std'] |
| 164 kwargs['improvement_direction'] = value_dict['improvement_direction'] |
| 160 | 165 |
| 161 if 'none_value_reason' in value_dict: | 166 if 'none_value_reason' in value_dict: |
| 162 kwargs['none_value_reason'] = value_dict['none_value_reason'] | 167 kwargs['none_value_reason'] = value_dict['none_value_reason'] |
| 163 if 'tir_label' in value_dict: | 168 if 'tir_label' in value_dict: |
| 164 kwargs['tir_label'] = value_dict['tir_label'] | 169 kwargs['tir_label'] = value_dict['tir_label'] |
| 165 | 170 |
| 166 return ListOfScalarValues(**kwargs) | 171 return ListOfScalarValues(**kwargs) |
| 167 | 172 |
| 168 @classmethod | 173 @classmethod |
| 169 def MergeLikeValuesFromSamePage(cls, values): | 174 def MergeLikeValuesFromSamePage(cls, values): |
| 170 assert len(values) > 0 | 175 assert len(values) > 0 |
| 171 v0 = values[0] | 176 v0 = values[0] |
| 172 | 177 |
| 173 if v0.same_page_merge_policy == value_module.PICK_FIRST: | 178 if v0.same_page_merge_policy == value_module.PICK_FIRST: |
| 174 return ListOfScalarValues( | 179 return ListOfScalarValues( |
| 175 v0.page, v0.name, v0.units, | 180 v0.page, v0.name, v0.units, |
| 176 values[0].values, | 181 values[0].values, |
| 177 important=v0.important, | 182 important=v0.important, |
| 178 same_page_merge_policy=v0.same_page_merge_policy, | 183 same_page_merge_policy=v0.same_page_merge_policy, |
| 179 none_value_reason=v0.none_value_reason) | 184 none_value_reason=v0.none_value_reason, |
| 185 improvement_direction=v0.improvement_direction) |
| 180 | 186 |
| 181 assert v0.same_page_merge_policy == value_module.CONCATENATE | 187 assert v0.same_page_merge_policy == value_module.CONCATENATE |
| 182 return cls._MergeLikeValues(values, v0.page, v0.name, v0.tir_label) | 188 return cls._MergeLikeValues(values, v0.page, v0.name, v0.tir_label) |
| 183 | 189 |
| 184 @classmethod | 190 @classmethod |
| 185 def MergeLikeValuesFromDifferentPages(cls, values): | 191 def MergeLikeValuesFromDifferentPages(cls, values): |
| 186 assert len(values) > 0 | 192 assert len(values) > 0 |
| 187 v0 = values[0] | 193 v0 = values[0] |
| 188 return cls._MergeLikeValues(values, None, v0.name, v0.tir_label) | 194 return cls._MergeLikeValues(values, None, v0.name, v0.tir_label) |
| 189 | 195 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 204 if merged_values: | 210 if merged_values: |
| 205 pooled_std = PooledStandardDeviation( | 211 pooled_std = PooledStandardDeviation( |
| 206 list_of_samples, list_of_variances=[v.variance for v in values]) | 212 list_of_samples, list_of_variances=[v.variance for v in values]) |
| 207 return ListOfScalarValues( | 213 return ListOfScalarValues( |
| 208 page, name, v0.units, | 214 page, name, v0.units, |
| 209 merged_values, | 215 merged_values, |
| 210 important=v0.important, | 216 important=v0.important, |
| 211 tir_label=tir_label, | 217 tir_label=tir_label, |
| 212 same_page_merge_policy=v0.same_page_merge_policy, | 218 same_page_merge_policy=v0.same_page_merge_policy, |
| 213 std=pooled_std, | 219 std=pooled_std, |
| 214 none_value_reason=none_value_reason) | 220 none_value_reason=none_value_reason, |
| 221 improvement_direction=v0.improvement_direction) |
| OLD | NEW |