Mercurial > hg > nsaunier > traffic-intelligence
comparison python/utils.py @ 614:5e09583275a4
Merged Nicolas/trafficintelligence into default
| author | Mohamed Gomaa <eng.m.gom3a@gmail.com> |
|---|---|
| date | Fri, 05 Dec 2014 12:13:53 -0500 |
| parents | c5406edbcf12 |
| children | 0954aaf28231 |
comparison
equal
deleted
inserted
replaced
| 598:11f96bd08552 | 614:5e09583275a4 |
|---|---|
| 1 #! /usr/bin/env python | 1 #! /usr/bin/env python |
| 2 ''' Generic utilities.''' | 2 ''' Generic utilities.''' |
| 3 | 3 |
| 4 #from numpy import * | 4 #from numpy import * |
| 5 #from pylab import * | 5 #from pylab import * |
| 6 from datetime import time, datetime | |
| 7 from math import sqrt | |
| 6 | 8 |
| 7 __metaclass__ = type | 9 __metaclass__ = type |
| 8 | 10 |
| 9 commentChar = '#' | 11 datetimeFormat = "%Y-%m-%d %H:%M:%S" |
| 10 | |
| 11 delimiterChar = '%'; | |
| 12 | 12 |
| 13 ######################### | 13 ######################### |
| 14 # Enumerations | 14 # Enumerations |
| 15 ######################### | 15 ######################### |
| 16 | 16 |
| 20 for i,x in enumerate(l): | 20 for i,x in enumerate(l): |
| 21 result[x] = i | 21 result[x] = i |
| 22 return result | 22 return result |
| 23 | 23 |
| 24 ######################### | 24 ######################### |
| 25 # CLI utils | |
| 26 ######################### | |
| 27 | |
| 28 def parseCLIOptions(helpMessage, options, cliArgs, optionalOptions=[]): | |
| 29 ''' Simple function to handle similar argument parsing | |
| 30 Returns the dictionary of options and their values | |
| 31 | |
| 32 * cliArgs are most likely directly sys.argv | |
| 33 (only the elements after the first one are considered) | |
| 34 | |
| 35 * options should be a list of strings for getopt options, | |
| 36 eg ['frame=','correspondences=','video='] | |
| 37 A value must be provided for each option, or the program quits''' | |
| 38 import sys, getopt | |
| 39 from numpy.core.fromnumeric import all | |
| 40 optionValues, args = getopt.getopt(cliArgs[1:], 'h', ['help']+options+optionalOptions) | |
| 41 optionValues = dict(optionValues) | |
| 42 | |
| 43 if '--help' in optionValues.keys() or '-h' in optionValues.keys(): | |
| 44 print(helpMessage+ | |
| 45 '\n - Compulsory options: '+' '.join([opt.replace('=','') for opt in options])+ | |
| 46 '\n - Non-compulsory options: '+' '.join([opt.replace('=','') for opt in optionalOptions])) | |
| 47 sys.exit() | |
| 48 | |
| 49 missingArgument = [('--'+opt.replace('=','') in optionValues.keys()) for opt in options] | |
| 50 if not all(missingArgument): | |
| 51 print('Missing argument') | |
| 52 print(optionValues) | |
| 53 sys.exit() | |
| 54 | |
| 55 return optionValues | |
| 56 | |
| 57 ######################### | |
| 58 # simple statistics | 25 # simple statistics |
| 59 ######################### | 26 ######################### |
| 60 | 27 |
| 61 def confidenceInterval(mean, stdev, nSamples, percentConfidence, printLatex = False): | 28 def sampleSize(stdev, tolerance, percentConfidence, printLatex = False): |
| 62 from math import sqrt | |
| 63 from scipy.stats.distributions import norm | 29 from scipy.stats.distributions import norm |
| 64 k = round(norm.ppf(0.5+percentConfidence/200., 0, 1)*100)/100. # 1.-(100-percentConfidence)/200. | 30 k = round(norm.ppf(0.5+percentConfidence/200., 0, 1)*100)/100. # 1.-(100-percentConfidence)/200. |
| 31 if printLatex: | |
| 32 print('${0}^2\\frac{{{1}^2}}{{{2}^2}}$'.format(k, stdev, tolerance)) | |
| 33 return (k*stdev/tolerance)**2 | |
| 34 | |
| 35 def confidenceInterval(mean, stdev, nSamples, percentConfidence, trueStd = True, printLatex = False): | |
| 36 '''if trueStd, use normal distribution, otherwise, Student | |
| 37 | |
| 38 Use otherwise t.interval or norm.interval | |
| 39 ex: norm.interval(0.95, loc = 0., scale = 2.3/sqrt(11)) | |
| 40 t.interval(0.95, 10, loc=1.2, scale = 2.3/sqrt(nSamples)) | |
| 41 loc is mean, scale is sigma/sqrt(n) (for Student, 10 is df)''' | |
| 42 from math import sqrt | |
| 43 from scipy.stats.distributions import norm, t | |
| 44 if trueStd: | |
| 45 k = round(norm.ppf(0.5+percentConfidence/200., 0, 1)*100)/100. # 1.-(100-percentConfidence)/200. | |
| 46 else: # use Student | |
| 47 k = round(t.ppf(0.5+percentConfidence/200., nSamples-1)*100)/100. | |
| 65 e = k*stdev/sqrt(nSamples) | 48 e = k*stdev/sqrt(nSamples) |
| 66 if printLatex: | 49 if printLatex: |
| 67 print('${0} \pm {1}\\frac{{{2}}}{{\sqrt{{{3}}}}}$'.format(mean, k, stdev, nSamples)) | 50 print('${0} \pm {1}\\frac{{{2}}}{{\sqrt{{{3}}}}}$'.format(mean, k, stdev, nSamples)) |
| 68 return mean-e, mean+e | 51 return mean-e, mean+e |
| 69 | 52 |
| 76 | 59 |
| 77 class EmpiricalDistribution: | 60 class EmpiricalDistribution: |
| 78 def nSamples(self): | 61 def nSamples(self): |
| 79 return sum(self.counts) | 62 return sum(self.counts) |
| 80 | 63 |
| 81 def cumulativeDensityFunction(sample): | 64 def cumulativeDensityFunction(sample, normalized = False): |
| 82 '''Returns the cumulative density function of the sample of a random variable''' | 65 '''Returns the cumulative density function of the sample of a random variable''' |
| 83 from numpy.core.multiarray import array | 66 from numpy import arange, cumsum |
| 84 from numpy.lib.function_base import unique | 67 xaxis = sorted(sample) |
| 85 from numpy.core.fromnumeric import sum | 68 counts = arange(1,len(sample)+1) # dtype = float |
| 86 a = array(sample) | 69 if normalized: |
| 87 a.sort() | 70 counts /= float(len(sample)) |
| 88 xaxis = unique(a) | |
| 89 counts = [sum(a <= x) for x in xaxis] | |
| 90 return xaxis, counts | 71 return xaxis, counts |
| 91 | 72 |
| 92 class EmpiricalDiscreteDistribution(EmpiricalDistribution): | 73 class EmpiricalDiscreteDistribution(EmpiricalDistribution): |
| 93 '''Class to represent a sample of a distribution for a discrete random variable | 74 '''Class to represent a sample of a distribution for a discrete random variable |
| 94 ''' | 75 ''' |
| 172 | 153 |
| 173 ######################### | 154 ######################### |
| 174 # maths section | 155 # maths section |
| 175 ######################### | 156 ######################### |
| 176 | 157 |
| 177 def LCSS(l1, l2, threshold, distance, delta = float('inf')): | 158 # def kernelSmoothing(sampleX, X, Y, weightFunc, halfwidth): |
| 178 '''returns the longest common subsequence similarity | 159 # '''Returns a smoothed weighted version of Y at the predefined values of sampleX |
| 179 based on the threshold on distance between two elements of lists l1, l2 | 160 # Sum_x weight(sample_x,x) * y(x)''' |
| 180 ''' | 161 # from numpy import zeros, array |
| 181 from numpy import zeros, int as npint | 162 # smoothed = zeros(len(sampleX)) |
| 182 m = len(l1) | 163 # for i,x in enumerate(sampleX): |
| 183 n = len(l2) | 164 # weights = array([weightFunc(x,xx, halfwidth) for xx in X]) |
| 184 similarity = zeros((m+1,n+1), dtype = npint) | 165 # if sum(weights)>0: |
| 185 for i in xrange(1,m+1): | 166 # smoothed[i] = sum(weights*Y)/sum(weights) |
| 186 for j in xrange(max(1,i-delta),min(n+1,i+delta)): | 167 # else: |
| 187 if distance(l1[i-1], l2[j-1])<=threshold: | 168 # smoothed[i] = 0 |
| 188 similarity[i][j] = similarity[i-1][j-1]+1 | 169 # return smoothed |
| 189 else: | 170 |
| 190 similarity[i][j] = max(similarity[i-1][j], similarity[i][j-1]) | 171 def kernelSmoothing(x, X, Y, weightFunc, halfwidth): |
| 191 return similarity[-1][-1] | 172 '''Returns the smoothed estimate of (X,Y) at x |
| 192 | 173 Sum_x weight(sample_x,x) * y(x)''' |
| 193 def framesToTime(nFrames, frameRate, initialTime = (0.,0.,0.)): | 174 from numpy import zeros, array |
| 194 'returns hour, minutes and seconds' | 175 weights = array([weightFunc(x,observedx, halfwidth) for observedx in X]) |
| 176 if sum(weights)>0: | |
| 177 return sum(weights*Y)/sum(weights) | |
| 178 else: | |
| 179 return 0 | |
| 180 | |
| 181 def uniform(center, x, halfwidth): | |
| 182 if abs(center-x)<halfwidth: | |
| 183 return 1. | |
| 184 else: | |
| 185 return 0. | |
| 186 | |
| 187 def gaussian(center, x, halfwidth): | |
| 188 from numpy import exp | |
| 189 return exp(-((center-x)/halfwidth)**2/2) | |
| 190 | |
| 191 def epanechnikov(center, x, halfwidth): | |
| 192 diff = abs(center-x) | |
| 193 if diff<halfwidth: | |
| 194 return 1.-(diff/halfwidth)**2 | |
| 195 else: | |
| 196 return 0. | |
| 197 | |
| 198 def triangular(center, x, halfwidth): | |
| 199 diff = abs(center-x) | |
| 200 if diff<halfwidth: | |
| 201 return 1.-abs(diff/halfwidth) | |
| 202 else: | |
| 203 return 0. | |
| 204 | |
| 205 def medianSmoothing(x, X, Y, halfwidth): | |
| 206 '''Returns the media of Y's corresponding to X's in the interval [x-halfwidth, x+halfwidth]''' | |
| 207 from numpy import median | |
| 208 return median([y for observedx, y in zip(X,Y) if abs(x-observedx)<halfwidth]) | |
| 209 | |
| 210 def argmaxDict(d): | |
| 211 return max(d, key=d.get) | |
| 212 | |
| 213 def framesToTime(nFrames, frameRate, initialTime = time()): | |
| 214 '''returns a datetime.time for the time in hour, minutes and seconds | |
| 215 initialTime is a datetime.time''' | |
| 195 from math import floor | 216 from math import floor |
| 196 from datetime import time | 217 seconds = int(floor(float(nFrames)/float(frameRate))+initialTime.hour*3600+initialTime.minute*60+initialTime.second) |
| 197 seconds = int(floor(float(nFrames)/float(frameRate))+initialTime[0]*3600+initialTime[1]*60+initialTime[2]) | |
| 198 h = int(floor(seconds/3600.)) | 218 h = int(floor(seconds/3600.)) |
| 199 seconds = seconds - h*3600 | 219 seconds = seconds - h*3600 |
| 200 m = int(floor(seconds/60)) | 220 m = int(floor(seconds/60)) |
| 201 seconds = seconds - m*60 | 221 seconds = seconds - m*60 |
| 202 return time(h, m, seconds) | 222 return time(h, m, seconds) |
| 223 | |
| 224 def timeToFrames(t, frameRate): | |
| 225 return frameRate*(t.hour*3600+t.minute*60+t.second) | |
| 203 | 226 |
| 204 def sortXY(X,Y): | 227 def sortXY(X,Y): |
| 205 'returns the sorted (x, Y(x)) sorted on X' | 228 'returns the sorted (x, Y(x)) sorted on X' |
| 206 D = {} | 229 D = {} |
| 207 for x, y in zip(X,Y): | 230 for x, y in zip(X,Y): |
| 215 from math import ceil,pow | 238 from math import ceil,pow |
| 216 tens = pow(10,nDecimals) | 239 tens = pow(10,nDecimals) |
| 217 return ceil(v*tens)/tens | 240 return ceil(v*tens)/tens |
| 218 | 241 |
| 219 def inBetween(bound1, bound2, x): | 242 def inBetween(bound1, bound2, x): |
| 220 return bound1 <= x <= bound2 or bound2 <= x<= bound1 | 243 return bound1 <= x <= bound2 or bound2 <= x <= bound1 |
| 244 | |
| 245 def pointDistanceL2(x1,y1,x2,y2): | |
| 246 ''' Compute point-to-point distance (L2 norm, ie Euclidean distance)''' | |
| 247 return sqrt((x2-x1)**2+(y2-y1)**2) | |
| 221 | 248 |
| 222 def crossProduct(l1, l2): | 249 def crossProduct(l1, l2): |
| 223 return l1[0]*l2[1]-l1[1]*l2[0] | 250 return l1[0]*l2[1]-l1[1]*l2[0] |
| 224 | 251 |
| 225 def filterMovingWindow(input, halfWidth): | 252 def cat_mvgavg(cat_list, halfWidth): |
| 253 ''' Return a list of categories/values smoothed according to a window. | |
| 254 halfWidth is the search radius on either side''' | |
| 255 from copy import deepcopy | |
| 256 catgories = deepcopy(cat_list) | |
| 257 smoothed = catgories | |
| 258 for point in range(len(catgories)): | |
| 259 lower_bound_check = max(0,point-halfWidth) | |
| 260 upper_bound_check = min(len(catgories)-1,point+halfWidth+1) | |
| 261 window_values = catgories[lower_bound_check:upper_bound_check] | |
| 262 smoothed[point] = max(set(window_values), key=window_values.count) | |
| 263 return smoothed | |
| 264 | |
| 265 def filterMovingWindow(inputSignal, halfWidth): | |
| 226 '''Returns an array obtained after the smoothing of the input by a moving average | 266 '''Returns an array obtained after the smoothing of the input by a moving average |
| 227 The first and last points are copied from the original.''' | 267 The first and last points are copied from the original.''' |
| 268 from numpy import ones,convolve,array | |
| 228 width = float(halfWidth*2+1) | 269 width = float(halfWidth*2+1) |
| 229 win = ones(width,'d') | 270 win = ones(width,'d') |
| 230 result = convolve(win/width,array(inputSignal),'same') | 271 result = convolve(win/width,array(inputSignal),'same') |
| 231 result[:halfWidth] = inputSignal[:halfWidth] | 272 result[:halfWidth] = inputSignal[:halfWidth] |
| 232 result[-halfWidth:] = inputSignal[-halfWidth:] | 273 result[-halfWidth:] = inputSignal[-halfWidth:] |
| 249 xx = arange(min(x), max(x),(max(x)-min(x))/1000) | 290 xx = arange(min(x), max(x),(max(x)-min(x))/1000) |
| 250 plot(xx, [poly(z) for z in xx]) | 291 plot(xx, [poly(z) for z in xx]) |
| 251 return coef | 292 return coef |
| 252 | 293 |
| 253 ######################### | 294 ######################### |
| 295 # iterable section | |
| 296 ######################### | |
| 297 | |
| 298 def mostCommon(L): | |
| 299 '''Returns the most frequent element in a iterable | |
| 300 | |
| 301 taken from http://stackoverflow.com/questions/1518522/python-most-common-element-in-a-list''' | |
| 302 from itertools import groupby | |
| 303 from operator import itemgetter | |
| 304 # get an iterable of (item, iterable) pairs | |
| 305 SL = sorted((x, i) for i, x in enumerate(L)) | |
| 306 # print 'SL:', SL | |
| 307 groups = groupby(SL, key=itemgetter(0)) | |
| 308 # auxiliary function to get "quality" for an item | |
| 309 def _auxfun(g): | |
| 310 item, iterable = g | |
| 311 count = 0 | |
| 312 min_index = len(L) | |
| 313 for _, where in iterable: | |
| 314 count += 1 | |
| 315 min_index = min(min_index, where) | |
| 316 # print 'item %r, count %r, minind %r' % (item, count, min_index) | |
| 317 return count, -min_index | |
| 318 # pick the highest-count/earliest item | |
| 319 return max(groups, key=_auxfun)[0] | |
| 320 | |
| 321 ######################### | |
| 322 # sequence section | |
| 323 ######################### | |
| 324 | |
| 325 class LCSS: | |
| 326 '''Class that keeps the LCSS parameters | |
| 327 and puts together the various computations''' | |
| 328 def __init__(self, similarityFunc, delta = float('inf'), aligned = False, lengthFunc = min): | |
| 329 self.similarityFunc = similarityFunc | |
| 330 self.aligned = aligned | |
| 331 self.delta = delta | |
| 332 self.lengthFunc = lengthFunc | |
| 333 self.subSequenceIndices = [(0,0)] | |
| 334 | |
| 335 def similarities(self, l1, l2, jshift=0): | |
| 336 from numpy import zeros, int as npint | |
| 337 n1 = len(l1) | |
| 338 n2 = len(l2) | |
| 339 self.similarityTable = zeros((n1+1,n2+1), dtype = npint) | |
| 340 for i in xrange(1,n1+1): | |
| 341 for j in xrange(max(1,i-jshift-self.delta),min(n2,i-jshift+self.delta)+1): | |
| 342 if self.similarityFunc(l1[i-1], l2[j-1]): | |
| 343 self.similarityTable[i,j] = self.similarityTable[i-1,j-1]+1 | |
| 344 else: | |
| 345 self.similarityTable[i,j] = max(self.similarityTable[i-1,j], self.similarityTable[i,j-1]) | |
| 346 | |
| 347 def subSequence(self, i, j): | |
| 348 '''Returns the subsequence of two sequences | |
| 349 http://en.wikipedia.org/wiki/Longest_common_subsequence_problem''' | |
| 350 if i == 0 or j == 0: | |
| 351 return [] | |
| 352 elif self.similarityTable[i][j] == self.similarityTable[i][j-1]: | |
| 353 return self.subSequence(i, j-1) | |
| 354 elif self.similarityTable[i][j] == self.similarityTable[i-1][j]: | |
| 355 return self.subSequence(i-1, j) | |
| 356 else: | |
| 357 return self.subSequence(i-1, j-1) + [(i-1,j-1)] | |
| 358 | |
| 359 def _compute(self, _l1, _l2, computeSubSequence = False): | |
| 360 '''returns the longest common subsequence similarity | |
| 361 based on the threshold on distance between two elements of lists l1, l2 | |
| 362 similarityFunc returns True or False whether the two points are considered similar | |
| 363 | |
| 364 if aligned, returns the best matching if using a finite delta by shiftinig the series alignments | |
| 365 | |
| 366 eg distance(p1, p2) < epsilon | |
| 367 ''' | |
| 368 if len(_l2) < len(_l1): # l1 is the shortest | |
| 369 l1 = _l2 | |
| 370 l2 = _l1 | |
| 371 revertIndices = True | |
| 372 else: | |
| 373 l1 = _l1 | |
| 374 l2 = _l2 | |
| 375 revertIndices = False | |
| 376 n1 = len(l1) | |
| 377 n2 = len(l2) | |
| 378 | |
| 379 if self.aligned: | |
| 380 lcssValues = {} | |
| 381 similarityTables = {} | |
| 382 for i in xrange(-n2-self.delta+1, n1+self.delta): # interval such that [i-shift-delta, i-shift+delta] is never empty, which happens when i-shift+delta < 1 or when i-shift-delta > n2 | |
| 383 self.similarities(l1, l2, i) | |
| 384 lcssValues[i] = self.similarityTable.max() | |
| 385 similarityTables[i] = self.similarityTable | |
| 386 #print self.similarityTable | |
| 387 alignmentShift = argmaxDict(lcssValues) # ideally get the medium alignment shift, the one that minimizes distance | |
| 388 self.similarityTable = similarityTables[alignmentShift] | |
| 389 else: | |
| 390 alignmentShift = 0 | |
| 391 self.similarities(l1, l2) | |
| 392 | |
| 393 # threshold values for the useful part of the similarity table are n2-n1-delta and n1-n2-delta | |
| 394 self.similarityTable = self.similarityTable[:min(n1, n2+alignmentShift+self.delta)+1, :min(n2, n1-alignmentShift+self.delta)+1] | |
| 395 | |
| 396 if computeSubSequence: | |
| 397 self.subSequenceIndices = self.subSequence(self.similarityTable.shape[0]-1, self.similarityTable.shape[1]-1) | |
| 398 if revertIndices: | |
| 399 self.subSequenceIndices = [(j,i) for i,j in self.subSequenceIndices] | |
| 400 return self.similarityTable[-1,-1] | |
| 401 | |
| 402 def compute(self, l1, l2, computeSubSequence = False): | |
| 403 '''get methods are to be shadowed in child classes ''' | |
| 404 return self._compute(l1, l2, computeSubSequence) | |
| 405 | |
| 406 def computeAlignment(self): | |
| 407 from numpy import mean | |
| 408 return mean([j-i for i,j in self.subSequenceIndices]) | |
| 409 | |
| 410 def _computeNormalized(self, l1, l2, computeSubSequence = False): | |
| 411 ''' compute the normalized LCSS | |
| 412 ie, the LCSS divided by the min or mean of the indicator lengths (using lengthFunc) | |
| 413 lengthFunc = lambda x,y:float(x,y)/2''' | |
| 414 return float(self._compute(l1, l2, computeSubSequence))/self.lengthFunc(len(l1), len(l2)) | |
| 415 | |
| 416 def computeNormalized(self, l1, l2, computeSubSequence = False): | |
| 417 return self._computeNormalized(l1, l2, computeSubSequence) | |
| 418 | |
| 419 def _computeDistance(self, l1, l2, computeSubSequence = False): | |
| 420 ''' compute the LCSS distance''' | |
| 421 return 1-self._computeNormalized(l1, l2, computeSubSequence) | |
| 422 | |
| 423 def computeDistance(self, l1, l2, computeSubSequence = False): | |
| 424 return self._computeDistance(l1, l2, computeSubSequence) | |
| 425 | |
| 426 ######################### | |
| 254 # plotting section | 427 # plotting section |
| 255 ######################### | 428 ######################### |
| 256 | 429 |
| 257 def stepPlot(X, firstX, lastX, initialCount = 0): | 430 def plotPolygon(poly, options = ''): |
| 258 '''for each value in x, increment by one the initial count | 431 'Plots shapely polygon poly' |
| 432 from numpy.core.multiarray import array | |
| 433 from matplotlib.pyplot import plot | |
| 434 from shapely.geometry import Polygon | |
| 435 | |
| 436 tmp = array(poly.exterior) | |
| 437 plot(tmp[:,0], tmp[:,1], options) | |
| 438 | |
| 439 def stepPlot(X, firstX, lastX, initialCount = 0, increment = 1): | |
| 440 '''for each value in X, increment by increment the initial count | |
| 259 returns the lists that can be plotted | 441 returns the lists that can be plotted |
| 260 to obtain a step plot increasing by one for each value in x, from first to last value''' | 442 to obtain a step plot increasing by one for each value in x, from first to last value |
| 443 firstX and lastX should be respectively smaller and larger than all elements in X''' | |
| 261 | 444 |
| 262 sortedX = [] | 445 sortedX = [] |
| 263 counts = [initialCount] | 446 counts = [initialCount] |
| 264 for x in sorted(X): | 447 for x in sorted(X): |
| 265 sortedX += [x,x] | 448 sortedX += [x,x] |
| 266 counts.append(counts[-1]) | 449 counts.append(counts[-1]) |
| 267 counts.append(counts[-1]+1) | 450 counts.append(counts[-1]+increment) |
| 268 counts.append(counts[-1]) | 451 counts.append(counts[-1]) |
| 269 return [firstX]+sortedX+[lastX], counts | 452 return [firstX]+sortedX+[lastX], counts |
| 270 | 453 |
| 271 class PlottingPropertyValues: | 454 class PlottingPropertyValues: |
| 272 def __init__(self, values): | 455 def __init__(self, values): |
| 300 | 483 |
| 301 ######################### | 484 ######################### |
| 302 # file I/O section | 485 # file I/O section |
| 303 ######################### | 486 ######################### |
| 304 | 487 |
| 305 def openCheck(filename, option = 'r', quit = False): | |
| 306 '''Open file filename in read mode by default | |
| 307 and checks it is open''' | |
| 308 try: | |
| 309 return open(filename, option) | |
| 310 except IOError: | |
| 311 print 'File %s could not be opened.' % filename | |
| 312 if quit: | |
| 313 from sys import exit | |
| 314 exit() | |
| 315 return None | |
| 316 | |
| 317 def readline(f, commentCharacter = commentChar): | |
| 318 '''Modified readline function to skip comments.''' | |
| 319 s = f.readline() | |
| 320 while (len(s) > 0) and s.startswith(commentCharacter): | |
| 321 s = f.readline() | |
| 322 return s.strip() | |
| 323 | |
| 324 def getLines(f, delimiterCharacter = delimiterChar): | |
| 325 '''Gets a complete entry (all the lines) in between delimiterChar.''' | |
| 326 dataStrings = [] | |
| 327 s = readline(f) | |
| 328 while (len(s) > 0) and (not s.startswith(delimiterCharacter)): | |
| 329 dataStrings += [s.strip()] | |
| 330 s = readline(f) | |
| 331 return dataStrings | |
| 332 | |
| 333 class FakeSecHead(object): | |
| 334 '''Add fake section header [asection] | |
| 335 | |
| 336 from http://stackoverflow.com/questions/2819696/parsing-properties-file-in-python/2819788#2819788 | |
| 337 use read_file in Python 3.2+ | |
| 338 ''' | |
| 339 def __init__(self, fp): | |
| 340 self.fp = fp | |
| 341 self.sechead = '[main]\n' | |
| 342 | |
| 343 def readline(self): | |
| 344 if self.sechead: | |
| 345 try: return self.sechead | |
| 346 finally: self.sechead = None | |
| 347 else: return self.fp.readline() | |
| 348 | |
| 349 def removeExtension(filename, delimiter = '.'): | 488 def removeExtension(filename, delimiter = '.'): |
| 350 '''Returns the filename minus the extension (all characters after last .)''' | 489 '''Returns the filename minus the extension (all characters after last .)''' |
| 351 i = filename.rfind(delimiter) | 490 i = filename.rfind(delimiter) |
| 352 if i>0: | 491 if i>0: |
| 353 return filename[:i] | 492 return filename[:i] |
| 384 if (os.path.exists(filename)): | 523 if (os.path.exists(filename)): |
| 385 os.remove(filename) | 524 os.remove(filename) |
| 386 else: | 525 else: |
| 387 print(filename+' does not exist') | 526 print(filename+' does not exist') |
| 388 | 527 |
| 389 def plotPolygon(poly, options = ''): | |
| 390 from numpy.core.multiarray import array | |
| 391 from matplotlib.pyplot import plot | |
| 392 from shapely.geometry import Polygon | |
| 393 | |
| 394 tmp = array(poly.exterior) | |
| 395 plot(tmp[:,0], tmp[:,1], options) | |
| 396 | |
| 397 def line2Floats(l, separator=' '): | 528 def line2Floats(l, separator=' '): |
| 398 '''Returns the list of floats corresponding to the string''' | 529 '''Returns the list of floats corresponding to the string''' |
| 399 return [float(x) for x in l.split(separator)] | 530 return [float(x) for x in l.split(separator)] |
| 400 | 531 |
| 401 def line2Ints(l, separator=' '): | 532 def line2Ints(l, separator=' '): |
| 402 '''Returns the list of ints corresponding to the string''' | 533 '''Returns the list of ints corresponding to the string''' |
| 403 return [int(x) for x in l.split(separator)] | 534 return [int(x) for x in l.split(separator)] |
| 404 | 535 |
| 405 ######################### | 536 ######################### |
| 406 # sqlite | 537 # CLI utils |
| 407 ######################### | 538 ######################### |
| 408 | 539 |
| 409 def dropTables(connection, tableNames): | 540 def parseCLIOptions(helpMessage, options, cliArgs, optionalOptions=[]): |
| 410 'deletes the table with names in tableNames' | 541 ''' Simple function to handle similar argument parsing |
| 411 cursor = connection.cursor() | 542 Returns the dictionary of options and their values |
| 412 for tableName in tableNames: | 543 |
| 413 cursor.execute('DROP TABLE '+tableName) | 544 * cliArgs are most likely directly sys.argv |
| 545 (only the elements after the first one are considered) | |
| 546 | |
| 547 * options should be a list of strings for getopt options, | |
| 548 eg ['frame=','correspondences=','video='] | |
| 549 A value must be provided for each option, or the program quits''' | |
| 550 import sys, getopt | |
| 551 from numpy.core.fromnumeric import all | |
| 552 optionValues, args = getopt.getopt(cliArgs[1:], 'h', ['help']+options+optionalOptions) | |
| 553 optionValues = dict(optionValues) | |
| 554 | |
| 555 if '--help' in optionValues.keys() or '-h' in optionValues.keys(): | |
| 556 print(helpMessage+ | |
| 557 '\n - Compulsory options: '+' '.join([opt.replace('=','') for opt in options])+ | |
| 558 '\n - Non-compulsory options: '+' '.join([opt.replace('=','') for opt in optionalOptions])) | |
| 559 sys.exit() | |
| 560 | |
| 561 missingArgument = [('--'+opt.replace('=','') in optionValues.keys()) for opt in options] | |
| 562 if not all(missingArgument): | |
| 563 print('Missing argument') | |
| 564 print(optionValues) | |
| 565 sys.exit() | |
| 566 | |
| 567 return optionValues | |
| 568 | |
| 569 | |
| 570 ######################### | |
| 571 # Profiling | |
| 572 ######################### | |
| 573 | |
| 574 def analyzeProfile(profileFilename, stripDirs = True): | |
| 575 '''Analyze the file produced by cProfile | |
| 576 | |
| 577 obtained by for example: | |
| 578 - call in script (for main() function in script) | |
| 579 import cProfile, os | |
| 580 cProfile.run('main()', os.path.join(os.getcwd(),'main.profile')) | |
| 581 | |
| 582 - or on the command line: | |
| 583 python -m cProfile [-o profile.bin] [-s sort] scriptfile [arg]''' | |
| 584 import pstats, os | |
| 585 p = pstats.Stats(os.path.join(os.pardir, profileFilename)) | |
| 586 if stripDirs: | |
| 587 p.strip_dirs() | |
| 588 p.sort_stats('time') | |
| 589 p.print_stats(.2) | |
| 590 #p.sort_stats('time') | |
| 591 # p.print_callees(.1, 'int_prediction.py:') | |
| 592 return p | |
| 414 | 593 |
| 415 ######################### | 594 ######################### |
| 416 # running tests | 595 # running tests |
| 417 ######################### | 596 ######################### |
| 418 | 597 |
