Mercurial Hosting > traffic-intelligence
view python/utils.py @ 279:3af4c267a7bf
generic simple LCSS
author | Nicolas Saunier <nicolas.saunier@polymtl.ca> |
---|---|
date | Thu, 20 Dec 2012 18:04:05 -0500 |
parents | 78922b4de3bf |
children | 4f012e3d881b |
line wrap: on
line source
#! /usr/bin/env python ''' Generic utilities.''' #from numpy import * #from pylab import * __metaclass__ = type commentChar = '#' delimiterChar = '%'; ######################### # Enumerations ######################### def inverseEnumeration(l): 'Returns the dictionary that provides for each element in the input list its index in the input list' result = {} for i,x in enumerate(l): result[x] = i return result ######################### # CLI utils ######################### def parseCLIOptions(helpMessage, options, cliArgs, optionalOptions=[]): ''' Simple function to handle similar argument parsing Returns the dictionary of options and their values * cliArgs are most likely directly sys.argv (only the elements after the first one are considered) * options should be a list of strings for getopt options, eg ['frame=','correspondences=','video='] A value must be provided for each option, or the program quits''' import sys, getopt from numpy.core.fromnumeric import all optionValues, args = getopt.getopt(cliArgs[1:], 'h', ['help']+options+optionalOptions) optionValues = dict(optionValues) if '--help' in optionValues.keys() or '-h' in optionValues.keys(): print(helpMessage+ '\n - Compulsory options: '+' '.join([opt.replace('=','') for opt in options])+ '\n - Non-compulsory options: '+' '.join([opt.replace('=','') for opt in optionalOptions])) sys.exit() missingArgument = [('--'+opt.replace('=','') in optionValues.keys()) for opt in options] if not all(missingArgument): print('Missing argument') print(optionValues) sys.exit() return optionValues ######################### # simple statistics ######################### def computeChi2(expected, observed): '''Returns the Chi2 statistics''' result = 0. for e, o in zip(expected, observed): result += ((e-o)*(e-o))/e return result class EmpiricalDistribution: def nSamples(self): return sum(self.counts) def cumulativeDensityFunction(sample): '''Returns the cumulative density function of the sample of a random variable''' from numpy.core.multiarray import array from numpy.lib.function_base import unique from numpy.core.fromnumeric import sum a = array(sample) a.sort() xaxis = unique(a) counts = [sum(a <= x) for x in xaxis] return xaxis, counts class EmpiricalDiscreteDistribution(EmpiricalDistribution): '''Class to represent a sample of a distribution for a discrete random variable ''' from numpy.core.fromnumeric import sum def __init__(self, categories, counts): self.categories = categories self.counts = counts def mean(self): result = [float(x*y) for x,y in zip(self.categories, self.counts)] return sum(result)/self.nSamples() def var(self, mean = None): if not mean: m = self.mean() else: m = mean result = 0. squares = [float((x-m)*(x-m)*y) for x,y in zip(self.categories, self.counts)] return sum(squares)/(self.nSamples()-1) def referenceCounts(self, probability): '''probability is a function that returns the probability of the random variable for the category values''' refProba = [probability(c) for c in self.categories] refProba[-1] = 1-sum(refProba[:-1]) refCounts = [r*self.nSamples() for r in refProba] return refCounts, refProba class EmpiricalContinuousDistribution(EmpiricalDistribution): '''Class to represent a sample of a distribution for a continuous random variable with the number of observations for each interval intervals (categories variable) are defined by their left limits, the last one being the right limit categories contain therefore one more element than the counts''' def __init__(self, categories, counts): # todo add samples for initialization and everything to None? (or setSamples?) self.categories = categories self.counts = counts def mean(self): result = 0. for i in range(len(self.counts)-1): result += self.counts[i]*(self.categories[i]+self.categories[i+1])/2 return result/self.nSamples() def var(self, mean = None): if not mean: m = self.mean() else: m = mean result = 0. for i in range(len(self.counts)-1): mid = (self.categories[i]+self.categories[i+1])/2 result += self.counts[i]*(mid - m)*(mid - m) return result/(self.nSamples()-1) def referenceCounts(self, cdf): '''cdf is a cumulative distribution function returning the probability of the variable being less that x''' # refCumulativeCounts = [0]#[cdf(self.categories[0][0])] # for inter in self.categories: # refCumulativeCounts.append(cdf(inter[1])) refCumulativeCounts = [cdf(x) for x in self.categories[1:-1]] refProba = [refCumulativeCounts[0]] for i in xrange(1,len(refCumulativeCounts)): refProba.append(refCumulativeCounts[i]-refCumulativeCounts[i-1]) refProba.append(1-refCumulativeCounts[-1]) refCounts = [p*self.nSamples() for p in refProba] return refCounts, refProba def printReferenceCounts(self, refCounts=None): if refCounts: ref = refCounts else: ref = self.referenceCounts for i in xrange(len(ref[0])): print('{0}-{1} & {2:0.3} & {3:0.3} \\\\'.format(self.categories[i],self.categories[i+1],ref[1][i], ref[0][i])) ######################### # maths section ######################### def LCSS(l1, l2, threshold, distance): "returns the longest common subsequence similarity based on the threshold on distance between two elements of lists l1, l2" from numpy import zeros m = len(l1) n = len(l2) similarity = zeros((m+1,n+1)) for i in xrange(1,m+1): for j in xrange(1,n+1): if distance(l1[i], l2[i])<threshold: similarity[i][j] = similarity(i-1, j-1)+1 else: similarity[i][j] = max(similarity[i-1][j], similarity[i][j-1]) return similarity[-1][-1] def framesToTime(nFrames, frameRate, initialTime = (0.,0.,0.)): 'returns hour, minutes and seconds' from math import floor from datetime import time seconds = int(floor(float(nFrames)/float(frameRate))+initialTime[0]*3600+initialTime[1]*60+initialTime[2]) h = int(floor(seconds/3600.)) seconds = seconds - h*3600 m = int(floor(seconds/60)) seconds = seconds - m*60 return time(h, m, seconds) def sortXY(X,Y): 'returns the sorted (x, Y(x)) sorted on X' D = {} for x, y in zip(X,Y): D[x]=y xsorted = sorted(D.keys()) return xsorted, [D[x] for x in xsorted] def ceilDecimals(v, nDecimals): '''Rounds the number at the nth decimal eg 1.23 at 0 decimal is 2, at 1 decimal is 1.3''' from math import ceil,pow tens = pow(10,nDecimals) return ceil(v*tens)/tens def inBetween(bound1, bound2, x): return bound1 <= x <= bound2 or bound2 <= x<= bound1 def crossProduct(l1, l2): return l1[0]*l2[1]-l1[1]*l2[0] def filterMovingWindow(input, halfWidth): '''Returns an array obtained after the smoothing of the input by a moving average The first and last points are copied from the original.''' width = float(halfWidth*2+1) win = ones(width,'d') result = convolve(win/width,array(inputSignal),'same') result[:halfWidth] = inputSignal[:halfWidth] result[-halfWidth:] = inputSignal[-halfWidth:] return result def linearRegression(x, y, deg = 1, plotData = False): '''returns the least square estimation of the linear regression of y = ax+b as well as the plot''' from numpy.lib.polynomial import polyfit from matplotlib.pyplot import plot from numpy.core.multiarray import arange coef = polyfit(x, y, deg) if plotData: def poly(x): result = 0 for i in range(len(coef)): result += coef[i]*x**(len(coef)-i-1) return result plot(x, y, 'x') xx = arange(min(x), max(x),(max(x)-min(x))/1000) plot(xx, [poly(z) for z in xx]) return coef ######################### # plotting section ######################### class PlottingPropertyValues: def __init__(self, values): self.values = values def __getitem__(self, i): return self.values[i%len(self.values)] markers = PlottingPropertyValues(['+', '*', ',', '.', 'x', 'D', 's', 'o']) scatterMarkers = PlottingPropertyValues(['s','o','^','>','v','<','d','p','h','8','+','x']) linestyles = PlottingPropertyValues(['-', '--', '-.', ':']) colors = PlottingPropertyValues('brgmyck') # 'w' def plotIndicatorMap(indicatorMap, squareSize, masked = True, defaultValue=-1): from numpy import array, arange, ones, ma from matplotlib.pyplot import pcolor coords = array(indicatorMap.keys()) minX = min(coords[:,0]) minY = min(coords[:,1]) X = arange(minX, max(coords[:,0])+1.1)*squareSize Y = arange(minY, max(coords[:,1])+1.1)*squareSize C = defaultValue*ones((len(Y), len(X))) for k,v in indicatorMap.iteritems(): C[k[1]-minY,k[0]-minX] = v if masked: pcolor(X, Y, ma.masked_where(C==defaultValue,C)) else: pcolor(X, Y, C) ######################### # file I/O section ######################### def openCheck(filename, option = 'r', quit = False): '''Open file filename in read mode by default and checks it is open''' try: return open(filename, option) except IOError: print 'File %s could not be opened.' % filename if quit: from sys import exit exit() return None def readline(f, commentCharacter = commentChar): '''Modified readline function to skip comments.''' s = f.readline() while (len(s) > 0) and s.startswith(commentCharacter): s = f.readline() return s.strip() def getLines(f, delimiterCharacter = delimiterChar): '''Gets a complete entry (all the lines) in between delimiterChar.''' dataStrings = [] s = readline(f) while (len(s) > 0) and (not s.startswith(delimiterCharacter)): dataStrings += [s.strip()] s = readline(f) return dataStrings def removeExtension(filename, delimiter = '.'): '''Returns the filename minus the extension (all characters after last .)''' i = filename.rfind(delimiter) if i>0: return filename[:i] else: return filename def cleanFilename(s): 'cleans filenames obtained when contatenating figure characteristics' return s.replace(' ','-').replace('.','').replace('/','-') def listfiles(dirname, extension, remove = False): '''Returns the list of files with the extension in the directory dirname If remove is True, the filenames are stripped from the extension''' from os import listdir tmp = [f for f in listdir(dirname) if f.endswith(extension)] tmp.sort() if remove: return [removeExtension(f, extension) for f in tmp] else: return tmp def mkdir(dirname): 'Creates a directory if it does not exist' import os if not os.path.exists(dirname): os.mkdir(dirname) else: print(dirname+' already exists') def removeFile(filename): '''Deletes the file while avoiding raising an error if the file does not exist''' import os if (os.path.exists(filename)): os.remove(filename) else: print(filename+' does not exist') def plotPolygon(poly, options = ''): from numpy.core.multiarray import array from matplotlib.pyplot import plot from shapely.geometry import Polygon tmp = array(poly.exterior) plot(tmp[:,0], tmp[:,1], options) def line2Floats(l, separator=' '): '''Returns the list of floats corresponding to the string''' return [float(x) for x in l.split(separator)] def line2Ints(l, separator=' '): '''Returns the list of ints corresponding to the string''' return [int(x) for x in l.split(separator)] ######################### # sqlite ######################### def dropTables(connection, tableNames): 'deletes the table with names in tableNames' cursor = connection.cursor() for tableName in tableNames: cursor.execute('DROP TABLE '+tableName) ######################### # running tests ######################### if __name__ == "__main__": import doctest import unittest suite = doctest.DocFileSuite('tests/utils.txt') #suite = doctest.DocTestSuite() unittest.TextTestRunner().run(suite) #doctest.testmod() #doctest.testfile("example.txt")