sumolib.statistics
1# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo 2# Copyright (C) 2012-2026 German Aerospace Center (DLR) and others. 3# This program and the accompanying materials are made available under the 4# terms of the Eclipse Public License 2.0 which is available at 5# https://www.eclipse.org/legal/epl-2.0/ 6# This Source Code may also be made available under the following Secondary 7# Licenses when the conditions for such availability set forth in the Eclipse 8# Public License 2.0 are satisfied: GNU General Public License, version 2 9# or later which is available at 10# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html 11# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later 12 13# @file statistics.py 14# @author Jakob Erdmann 15# @author Michael Behrisch 16# @date 2012-05-08 17 18from __future__ import absolute_import 19from __future__ import print_function 20from __future__ import division 21import math 22import warnings 23from collections import defaultdict 24try: 25 from numpy import sqrt, set_printoptions 26except ImportError: 27 from math import sqrt 28 29 30def round(value): # to round in Python 3 like in Python 2 31 if value < 0: 32 return math.ceil(value - 0.5) 33 else: 34 return math.floor(value + 0.5) 35 36 37def identity(value): 38 return value 39 40 41class _ExtremeType(object): 42 """ 43 see http://www.python.org/dev/peps/pep-0326/ 44 """ 45 46 def __init__(self, isMax, rep): 47 object.__init__(self) 48 self._isMax = isMax 49 self._rep = rep 50 51 def __eq__(self, other): 52 return isinstance(other, self.__class__) and other._isMax == self._isMax 53 54 def __ne__(self, other): 55 return not self == other 56 57 def __gt__(self, other): 58 return self._isMax and not self == other 59 60 def __ge__(self, other): 61 return self._isMax 62 63 def __lt__(self, other): 64 return not self._isMax and not self == other 65 66 def __le__(self, other): 67 return not self._isMax 68 69 def __repr__(self): 70 return self._rep 71 72 73uMax = _ExtremeType(True, "uMax") 74uMin = _ExtremeType(False, "uMin") 75 76 77def setPrecision(formatstr, precision, isArray=False, preformatted=False): 78 if isArray: 79 set_printoptions(precision=2) 80 return formatstr.replace('%.2f', '%s') 81 elif preformatted: 82 return formatstr.replace('%.2f', '%s') 83 else: 84 return formatstr.replace('%.2f', '%.' + str(int(precision)) + 'f') 85 86 87class Statistics: 88 89 def __init__(self, label=None, abs=False, histogram=False, printMin=True, scale=1, printDev=False, printSum=False): 90 self.label = label 91 self.min = uMax 92 self.min_label = None 93 self.max = uMin 94 self.max_label = None 95 self.values = [] 96 self.abs = abs 97 self.printMin = printMin 98 self.scale = scale 99 self.printDev = printDev 100 self.printSum = printSum 101 self.isArray = False 102 if histogram: 103 self.counts = defaultdict(int) 104 else: 105 self.counts = None 106 107 def add(self, v, label=None): 108 self.values.append(v) 109 isMin = v < self.min 110 if type(isMin) is not bool: 111 self.isArray = True 112 v = tuple(v) 113 if v < self.min: 114 self.min = v 115 self.min_label = label 116 if v > self.max: 117 self.max = v 118 self.max_label = label 119 if self.counts is not None: 120 self.counts[int(round(v / self.scale))] += 1 121 122 def update(self, other): 123 for v in other.values: 124 self.add(v) 125 126 def clear(self): 127 self.min = uMax 128 self.min_label = None 129 self.max = uMin 130 self.max_label = None 131 self.values = [] 132 if self.counts: 133 self.counts.clear() 134 135 def count(self): 136 return len(self.values) 137 138 def avg(self): 139 """return the mean value""" 140 # XXX rename this method 141 if len(self.values) > 0: 142 return sum(self.values) / float(len(self.values)) 143 else: 144 return None 145 146 def avg_abs(self): 147 """return the mean of absolute values""" 148 # XXX rename this method 149 if len(self.values) > 0: 150 return sum(map(abs, self.values)) / float(len(self.values)) 151 else: 152 return None 153 154 def meanAndStdDev(self, limit=None): 155 """return the mean and the standard deviation optionally limited to the last limit values""" 156 if limit is None or len(self.values) < limit: 157 limit = len(self.values) 158 if limit > 0: 159 mean = sum(self.values[-limit:]) / float(limit) 160 sumSq = 0. 161 for v in self.values[-limit:]: 162 sumSq += (v - mean) * (v - mean) 163 return mean, sqrt(sumSq / limit) 164 else: 165 return None 166 167 def relStdDev(self, limit=None): 168 """return the relative standard deviation optionally limited to the last limit values""" 169 moments = self.meanAndStdDev(limit) 170 if moments is None: 171 return None 172 return moments[1] / moments[0] 173 174 def mean(self): 175 warnings.warn("mean() is deprecated, because the name is misleading, use median() instead") 176 return self.median() 177 178 def mean_abs(self): 179 warnings.warn("mean_abs() is deprecated, because the name is misleading, use median_abs() instead") 180 return self.median_abs() 181 182 def average_absolute_deviation_from_mean(self): 183 if len(self.values) > 0: 184 m = self.avg() 185 return sum([abs(v - m) for v in self.values]) / len(self.values) 186 else: 187 return None 188 189 def median(self): 190 """return the median value""" 191 if len(self.values) > 0: 192 return sorted(self.values)[len(self.values) // 2] 193 else: 194 return None 195 196 def median_abs(self): 197 """return the median of absolute values""" 198 if len(self.values) > 0: 199 return sorted(map(abs, self.values))[len(self.values) // 2] 200 else: 201 return None 202 203 def quartiles(self): 204 s = sorted(self.values, key=lambda v: tuple(v) if self.isArray else v) 205 return s[len(self.values) // 4], s[len(self.values) // 2], s[3 * len(self.values) // 4] 206 207 def rank(self, fraction): 208 if len(self.values) > 0: 209 return sorted(self.values)[int(round(len(self.values) * fraction + 0.5))] 210 else: 211 return None 212 213 def histogram(self): 214 if self.counts is not None: 215 return [(k * self.scale, self.counts[k]) for k in sorted(self.counts.keys())] 216 else: 217 return "Histogramm is deactivated" 218 219 def toString(self, precision=2, histStyle=1, fmt=identity): 220 """histStyle 221 0 : not shown 222 1 : one line 223 2 : fancy 224 """ 225 if len(self.values) > 0: 226 pre = fmt != identity 227 min = '' 228 if self.printMin: 229 min = setPrecision('min %.2f%s, ', precision, self.isArray, pre) % ( 230 fmt(self.min), ('' if self.min_label is None else ' (%s)' % (self.min_label,))) 231 result = setPrecision('%s: count %s, %smax %.2f%s, mean %.2f', precision, self.isArray, pre) % ( 232 self.label, len(self.values), min, 233 fmt(self.max), 234 ('' if self.max_label is None else ' (%s)' % 235 (self.max_label,)), 236 fmt(self.avg())) 237 result += setPrecision(', Q1 %.2f, median %.2f, Q3 %.2f', precision, self.isArray, pre) % ( 238 tuple(map(fmt, self.quartiles()))) 239 if self.abs: 240 result += setPrecision(', mean_abs %.2f, median_abs %.2f', precision, self.isArray, pre) % ( 241 fmt(self.avg_abs()), fmt(self.median_abs())) 242 if self.printDev: 243 result += (setPrecision(', stdDev %.2f', precision, self.isArray) % (self.meanAndStdDev()[1])) 244 if self.printSum: 245 result += (setPrecision(', sum %.2f', precision, self.isArray) % sum(self.values)) 246 if self.counts is not None: 247 if histStyle == 1: 248 result += '\n histogram: %s' % self.histogram() 249 elif histStyle == 2: 250 keylen = len("%.0f" % (self.scale * max(self.counts.keys()))) 251 formatStr = "%%%i.0f: %%s" % keylen 252 result = 'histogram of %s:\n%s\n%s' % (self.label, 253 '\n'.join([formatStr % x for x in self.histogram()]), 254 result) 255 return result 256 else: 257 return '%s: no values' % self.label 258 259 def toXML(self, precision=2, tag="statistic", indent=4, label=None, fmt=identity, extraAttributes={}): 260 pre = fmt != identity 261 if label is None: 262 label = self.label 263 description = ' description="%s"' % label if label != '' else '' 264 265 result = ' ' * indent + '<%s%s' % (tag, description) 266 for k, v in extraAttributes.items(): 267 result += ' %s="%s"' % (k, v) 268 if self.count() > 0: 269 result += ' count="%i"' % self.count() 270 result += (setPrecision(' min="%.2f" minLabel="%s" max="%.2f" maxLabel="%s" mean="%.2f"', 271 precision, self.isArray, pre) % 272 (fmt(self.min), self.min_label, fmt(self.max), self.max_label, fmt(self.avg()))) 273 result += setPrecision(' Q1="%.2f" median="%.2f" Q3="%.2f"', precision, self.isArray, pre) % ( 274 tuple(map(fmt, self.quartiles()))) 275 result += (setPrecision(' meanAbs="%.2f" medianAbs="%.2f"', precision, self.isArray, pre) % 276 (fmt(self.avg_abs()), fmt(self.median_abs()))) 277 if self.printDev: 278 result += (setPrecision(' stdDev="%.2f"', precision, self.isArray) % 279 (self.meanAndStdDev()[1])) 280 if self.counts is not None: 281 result += '>\n' 282 for kv in self.histogram(): 283 result += setPrecision(8 * ' ' + '<hist key="%.2f" value="%i"/>\n', precision, self.isArray) % kv 284 result += ' ' * indent + '</%s>\n' % tag 285 else: 286 result += '/>\n' 287 return result 288 289 def __str__(self): 290 return self.toString() 291 292 def normalise_to_range(self, n_min=0, n_max=1): 293 """Normalises the stored list of values between n_min and n_max, Default: [0,1]""" 294 ret = [] 295 range_length = n_max - n_min 296 values_diff = max(self.values) - min(self.values) 297 for val in self.values: 298 temp = (((val - min(self.values))*range_length)/values_diff) + n_min 299 ret.append(temp) 300 return ret 301 302 303def geh(m, c): 304 """Error function for hourly traffic flow measures after Geoffrey E. Havers""" 305 if m + c == 0: 306 return 0 307 else: 308 return math.sqrt(2 * (m - c) * (m - c) / (m + c)) 309 310 311def sqv(self, m, c, scaling_factor=1000): 312 """Scaling Quality Value Calculation, Ref: https://journals.sagepub.com/doi/10.1177/0361198119838849 313 scaling_factor: 314 Number of person trips per day (total, per mode, per purpose) : 1 315 Mean trip distance in kilometers : 10 316 Duration of all trips per person per day in minutes : 100 317 Traffic volume per hour : 1000 318 Traffic volume per day : 10000 319 """ 320 return 1/(1 + math.sqrt(((m-c)*(m-c))/(scaling_factor*c)))
78def setPrecision(formatstr, precision, isArray=False, preformatted=False): 79 if isArray: 80 set_printoptions(precision=2) 81 return formatstr.replace('%.2f', '%s') 82 elif preformatted: 83 return formatstr.replace('%.2f', '%s') 84 else: 85 return formatstr.replace('%.2f', '%.' + str(int(precision)) + 'f')
88class Statistics: 89 90 def __init__(self, label=None, abs=False, histogram=False, printMin=True, scale=1, printDev=False, printSum=False): 91 self.label = label 92 self.min = uMax 93 self.min_label = None 94 self.max = uMin 95 self.max_label = None 96 self.values = [] 97 self.abs = abs 98 self.printMin = printMin 99 self.scale = scale 100 self.printDev = printDev 101 self.printSum = printSum 102 self.isArray = False 103 if histogram: 104 self.counts = defaultdict(int) 105 else: 106 self.counts = None 107 108 def add(self, v, label=None): 109 self.values.append(v) 110 isMin = v < self.min 111 if type(isMin) is not bool: 112 self.isArray = True 113 v = tuple(v) 114 if v < self.min: 115 self.min = v 116 self.min_label = label 117 if v > self.max: 118 self.max = v 119 self.max_label = label 120 if self.counts is not None: 121 self.counts[int(round(v / self.scale))] += 1 122 123 def update(self, other): 124 for v in other.values: 125 self.add(v) 126 127 def clear(self): 128 self.min = uMax 129 self.min_label = None 130 self.max = uMin 131 self.max_label = None 132 self.values = [] 133 if self.counts: 134 self.counts.clear() 135 136 def count(self): 137 return len(self.values) 138 139 def avg(self): 140 """return the mean value""" 141 # XXX rename this method 142 if len(self.values) > 0: 143 return sum(self.values) / float(len(self.values)) 144 else: 145 return None 146 147 def avg_abs(self): 148 """return the mean of absolute values""" 149 # XXX rename this method 150 if len(self.values) > 0: 151 return sum(map(abs, self.values)) / float(len(self.values)) 152 else: 153 return None 154 155 def meanAndStdDev(self, limit=None): 156 """return the mean and the standard deviation optionally limited to the last limit values""" 157 if limit is None or len(self.values) < limit: 158 limit = len(self.values) 159 if limit > 0: 160 mean = sum(self.values[-limit:]) / float(limit) 161 sumSq = 0. 162 for v in self.values[-limit:]: 163 sumSq += (v - mean) * (v - mean) 164 return mean, sqrt(sumSq / limit) 165 else: 166 return None 167 168 def relStdDev(self, limit=None): 169 """return the relative standard deviation optionally limited to the last limit values""" 170 moments = self.meanAndStdDev(limit) 171 if moments is None: 172 return None 173 return moments[1] / moments[0] 174 175 def mean(self): 176 warnings.warn("mean() is deprecated, because the name is misleading, use median() instead") 177 return self.median() 178 179 def mean_abs(self): 180 warnings.warn("mean_abs() is deprecated, because the name is misleading, use median_abs() instead") 181 return self.median_abs() 182 183 def average_absolute_deviation_from_mean(self): 184 if len(self.values) > 0: 185 m = self.avg() 186 return sum([abs(v - m) for v in self.values]) / len(self.values) 187 else: 188 return None 189 190 def median(self): 191 """return the median value""" 192 if len(self.values) > 0: 193 return sorted(self.values)[len(self.values) // 2] 194 else: 195 return None 196 197 def median_abs(self): 198 """return the median of absolute values""" 199 if len(self.values) > 0: 200 return sorted(map(abs, self.values))[len(self.values) // 2] 201 else: 202 return None 203 204 def quartiles(self): 205 s = sorted(self.values, key=lambda v: tuple(v) if self.isArray else v) 206 return s[len(self.values) // 4], s[len(self.values) // 2], s[3 * len(self.values) // 4] 207 208 def rank(self, fraction): 209 if len(self.values) > 0: 210 return sorted(self.values)[int(round(len(self.values) * fraction + 0.5))] 211 else: 212 return None 213 214 def histogram(self): 215 if self.counts is not None: 216 return [(k * self.scale, self.counts[k]) for k in sorted(self.counts.keys())] 217 else: 218 return "Histogramm is deactivated" 219 220 def toString(self, precision=2, histStyle=1, fmt=identity): 221 """histStyle 222 0 : not shown 223 1 : one line 224 2 : fancy 225 """ 226 if len(self.values) > 0: 227 pre = fmt != identity 228 min = '' 229 if self.printMin: 230 min = setPrecision('min %.2f%s, ', precision, self.isArray, pre) % ( 231 fmt(self.min), ('' if self.min_label is None else ' (%s)' % (self.min_label,))) 232 result = setPrecision('%s: count %s, %smax %.2f%s, mean %.2f', precision, self.isArray, pre) % ( 233 self.label, len(self.values), min, 234 fmt(self.max), 235 ('' if self.max_label is None else ' (%s)' % 236 (self.max_label,)), 237 fmt(self.avg())) 238 result += setPrecision(', Q1 %.2f, median %.2f, Q3 %.2f', precision, self.isArray, pre) % ( 239 tuple(map(fmt, self.quartiles()))) 240 if self.abs: 241 result += setPrecision(', mean_abs %.2f, median_abs %.2f', precision, self.isArray, pre) % ( 242 fmt(self.avg_abs()), fmt(self.median_abs())) 243 if self.printDev: 244 result += (setPrecision(', stdDev %.2f', precision, self.isArray) % (self.meanAndStdDev()[1])) 245 if self.printSum: 246 result += (setPrecision(', sum %.2f', precision, self.isArray) % sum(self.values)) 247 if self.counts is not None: 248 if histStyle == 1: 249 result += '\n histogram: %s' % self.histogram() 250 elif histStyle == 2: 251 keylen = len("%.0f" % (self.scale * max(self.counts.keys()))) 252 formatStr = "%%%i.0f: %%s" % keylen 253 result = 'histogram of %s:\n%s\n%s' % (self.label, 254 '\n'.join([formatStr % x for x in self.histogram()]), 255 result) 256 return result 257 else: 258 return '%s: no values' % self.label 259 260 def toXML(self, precision=2, tag="statistic", indent=4, label=None, fmt=identity, extraAttributes={}): 261 pre = fmt != identity 262 if label is None: 263 label = self.label 264 description = ' description="%s"' % label if label != '' else '' 265 266 result = ' ' * indent + '<%s%s' % (tag, description) 267 for k, v in extraAttributes.items(): 268 result += ' %s="%s"' % (k, v) 269 if self.count() > 0: 270 result += ' count="%i"' % self.count() 271 result += (setPrecision(' min="%.2f" minLabel="%s" max="%.2f" maxLabel="%s" mean="%.2f"', 272 precision, self.isArray, pre) % 273 (fmt(self.min), self.min_label, fmt(self.max), self.max_label, fmt(self.avg()))) 274 result += setPrecision(' Q1="%.2f" median="%.2f" Q3="%.2f"', precision, self.isArray, pre) % ( 275 tuple(map(fmt, self.quartiles()))) 276 result += (setPrecision(' meanAbs="%.2f" medianAbs="%.2f"', precision, self.isArray, pre) % 277 (fmt(self.avg_abs()), fmt(self.median_abs()))) 278 if self.printDev: 279 result += (setPrecision(' stdDev="%.2f"', precision, self.isArray) % 280 (self.meanAndStdDev()[1])) 281 if self.counts is not None: 282 result += '>\n' 283 for kv in self.histogram(): 284 result += setPrecision(8 * ' ' + '<hist key="%.2f" value="%i"/>\n', precision, self.isArray) % kv 285 result += ' ' * indent + '</%s>\n' % tag 286 else: 287 result += '/>\n' 288 return result 289 290 def __str__(self): 291 return self.toString() 292 293 def normalise_to_range(self, n_min=0, n_max=1): 294 """Normalises the stored list of values between n_min and n_max, Default: [0,1]""" 295 ret = [] 296 range_length = n_max - n_min 297 values_diff = max(self.values) - min(self.values) 298 for val in self.values: 299 temp = (((val - min(self.values))*range_length)/values_diff) + n_min 300 ret.append(temp) 301 return ret
90 def __init__(self, label=None, abs=False, histogram=False, printMin=True, scale=1, printDev=False, printSum=False): 91 self.label = label 92 self.min = uMax 93 self.min_label = None 94 self.max = uMin 95 self.max_label = None 96 self.values = [] 97 self.abs = abs 98 self.printMin = printMin 99 self.scale = scale 100 self.printDev = printDev 101 self.printSum = printSum 102 self.isArray = False 103 if histogram: 104 self.counts = defaultdict(int) 105 else: 106 self.counts = None
108 def add(self, v, label=None): 109 self.values.append(v) 110 isMin = v < self.min 111 if type(isMin) is not bool: 112 self.isArray = True 113 v = tuple(v) 114 if v < self.min: 115 self.min = v 116 self.min_label = label 117 if v > self.max: 118 self.max = v 119 self.max_label = label 120 if self.counts is not None: 121 self.counts[int(round(v / self.scale))] += 1
139 def avg(self): 140 """return the mean value""" 141 # XXX rename this method 142 if len(self.values) > 0: 143 return sum(self.values) / float(len(self.values)) 144 else: 145 return None
return the mean value
147 def avg_abs(self): 148 """return the mean of absolute values""" 149 # XXX rename this method 150 if len(self.values) > 0: 151 return sum(map(abs, self.values)) / float(len(self.values)) 152 else: 153 return None
return the mean of absolute values
155 def meanAndStdDev(self, limit=None): 156 """return the mean and the standard deviation optionally limited to the last limit values""" 157 if limit is None or len(self.values) < limit: 158 limit = len(self.values) 159 if limit > 0: 160 mean = sum(self.values[-limit:]) / float(limit) 161 sumSq = 0. 162 for v in self.values[-limit:]: 163 sumSq += (v - mean) * (v - mean) 164 return mean, sqrt(sumSq / limit) 165 else: 166 return None
return the mean and the standard deviation optionally limited to the last limit values
168 def relStdDev(self, limit=None): 169 """return the relative standard deviation optionally limited to the last limit values""" 170 moments = self.meanAndStdDev(limit) 171 if moments is None: 172 return None 173 return moments[1] / moments[0]
return the relative standard deviation optionally limited to the last limit values
190 def median(self): 191 """return the median value""" 192 if len(self.values) > 0: 193 return sorted(self.values)[len(self.values) // 2] 194 else: 195 return None
return the median value
197 def median_abs(self): 198 """return the median of absolute values""" 199 if len(self.values) > 0: 200 return sorted(map(abs, self.values))[len(self.values) // 2] 201 else: 202 return None
return the median of absolute values
220 def toString(self, precision=2, histStyle=1, fmt=identity): 221 """histStyle 222 0 : not shown 223 1 : one line 224 2 : fancy 225 """ 226 if len(self.values) > 0: 227 pre = fmt != identity 228 min = '' 229 if self.printMin: 230 min = setPrecision('min %.2f%s, ', precision, self.isArray, pre) % ( 231 fmt(self.min), ('' if self.min_label is None else ' (%s)' % (self.min_label,))) 232 result = setPrecision('%s: count %s, %smax %.2f%s, mean %.2f', precision, self.isArray, pre) % ( 233 self.label, len(self.values), min, 234 fmt(self.max), 235 ('' if self.max_label is None else ' (%s)' % 236 (self.max_label,)), 237 fmt(self.avg())) 238 result += setPrecision(', Q1 %.2f, median %.2f, Q3 %.2f', precision, self.isArray, pre) % ( 239 tuple(map(fmt, self.quartiles()))) 240 if self.abs: 241 result += setPrecision(', mean_abs %.2f, median_abs %.2f', precision, self.isArray, pre) % ( 242 fmt(self.avg_abs()), fmt(self.median_abs())) 243 if self.printDev: 244 result += (setPrecision(', stdDev %.2f', precision, self.isArray) % (self.meanAndStdDev()[1])) 245 if self.printSum: 246 result += (setPrecision(', sum %.2f', precision, self.isArray) % sum(self.values)) 247 if self.counts is not None: 248 if histStyle == 1: 249 result += '\n histogram: %s' % self.histogram() 250 elif histStyle == 2: 251 keylen = len("%.0f" % (self.scale * max(self.counts.keys()))) 252 formatStr = "%%%i.0f: %%s" % keylen 253 result = 'histogram of %s:\n%s\n%s' % (self.label, 254 '\n'.join([formatStr % x for x in self.histogram()]), 255 result) 256 return result 257 else: 258 return '%s: no values' % self.label
histStyle 0 : not shown 1 : one line 2 : fancy
260 def toXML(self, precision=2, tag="statistic", indent=4, label=None, fmt=identity, extraAttributes={}): 261 pre = fmt != identity 262 if label is None: 263 label = self.label 264 description = ' description="%s"' % label if label != '' else '' 265 266 result = ' ' * indent + '<%s%s' % (tag, description) 267 for k, v in extraAttributes.items(): 268 result += ' %s="%s"' % (k, v) 269 if self.count() > 0: 270 result += ' count="%i"' % self.count() 271 result += (setPrecision(' min="%.2f" minLabel="%s" max="%.2f" maxLabel="%s" mean="%.2f"', 272 precision, self.isArray, pre) % 273 (fmt(self.min), self.min_label, fmt(self.max), self.max_label, fmt(self.avg()))) 274 result += setPrecision(' Q1="%.2f" median="%.2f" Q3="%.2f"', precision, self.isArray, pre) % ( 275 tuple(map(fmt, self.quartiles()))) 276 result += (setPrecision(' meanAbs="%.2f" medianAbs="%.2f"', precision, self.isArray, pre) % 277 (fmt(self.avg_abs()), fmt(self.median_abs()))) 278 if self.printDev: 279 result += (setPrecision(' stdDev="%.2f"', precision, self.isArray) % 280 (self.meanAndStdDev()[1])) 281 if self.counts is not None: 282 result += '>\n' 283 for kv in self.histogram(): 284 result += setPrecision(8 * ' ' + '<hist key="%.2f" value="%i"/>\n', precision, self.isArray) % kv 285 result += ' ' * indent + '</%s>\n' % tag 286 else: 287 result += '/>\n' 288 return result
293 def normalise_to_range(self, n_min=0, n_max=1): 294 """Normalises the stored list of values between n_min and n_max, Default: [0,1]""" 295 ret = [] 296 range_length = n_max - n_min 297 values_diff = max(self.values) - min(self.values) 298 for val in self.values: 299 temp = (((val - min(self.values))*range_length)/values_diff) + n_min 300 ret.append(temp) 301 return ret
Normalises the stored list of values between n_min and n_max, Default: [0,1]
304def geh(m, c): 305 """Error function for hourly traffic flow measures after Geoffrey E. Havers""" 306 if m + c == 0: 307 return 0 308 else: 309 return math.sqrt(2 * (m - c) * (m - c) / (m + c))
Error function for hourly traffic flow measures after Geoffrey E. Havers
312def sqv(self, m, c, scaling_factor=1000): 313 """Scaling Quality Value Calculation, Ref: https://journals.sagepub.com/doi/10.1177/0361198119838849 314 scaling_factor: 315 Number of person trips per day (total, per mode, per purpose) : 1 316 Mean trip distance in kilometers : 10 317 Duration of all trips per person per day in minutes : 100 318 Traffic volume per hour : 1000 319 Traffic volume per day : 10000 320 """ 321 return 1/(1 + math.sqrt(((m-c)*(m-c))/(scaling_factor*c)))
Scaling Quality Value Calculation, Ref: https://journals.sagepub.com/doi/10.1177/0361198119838849 scaling_factor: Number of person trips per day (total, per mode, per purpose) : 1 Mean trip distance in kilometers : 10 Duration of all trips per person per day in minutes : 100 Traffic volume per hour : 1000 Traffic volume per day : 10000