Mercurial > hg > nsaunier > traffic-intelligence
comparison python/storage.py @ 750:6049e9b6902c dev
work in progress storage vissim sqlite
| author | Nicolas Saunier <nicolas.saunier@polymtl.ca> |
|---|---|
| date | Wed, 28 Oct 2015 17:50:32 -0400 |
| parents | ed6ff2ec0aeb |
| children | 79405a938407 |
comparison
equal
deleted
inserted
replaced
| 749:10dbab1e871d | 750:6049e9b6902c |
|---|---|
| 1 #! /usr/bin/env python | 1 #! /usr/bin/env python |
| 2 # -*- coding: utf-8 -*- | 2 # -*- coding: utf-8 -*- |
| 3 '''Various utilities to save and load data''' | 3 '''Various utilities to save and load data''' |
| 4 | 4 |
| 5 import utils, moving, events, indicators | 5 import utils, moving, events, indicators, shutil |
| 6 from base import VideoFilenameAddable | 6 from base import VideoFilenameAddable |
| 7 | 7 |
| 8 import sqlite3, logging | 8 import sqlite3, logging |
| 9 from numpy import log, min as npmin, max as npmax, round as npround, array, sum as npsum, loadtxt | 9 from numpy import log, min as npmin, max as npmax, round as npround, array, sum as npsum, loadtxt |
| 10 | 10 |
| 161 returns a moving object''' | 161 returns a moving object''' |
| 162 cursor = connection.cursor() | 162 cursor = connection.cursor() |
| 163 | 163 |
| 164 try: | 164 try: |
| 165 objectCriteria = getObjectCriteria(objectNumbers) | 165 objectCriteria = getObjectCriteria(objectNumbers) |
| 166 queryStatement = None | |
| 166 if trajectoryType == 'feature': | 167 if trajectoryType == 'feature': |
| 167 queryStatement = 'SELECT * from '+tableName | 168 queryStatement = 'SELECT * from '+tableName |
| 168 if objectNumbers is not None: | 169 if objectNumbers is not None: |
| 169 queryStatement += ' where trajectory_id '+objectCriteria | 170 queryStatement += ' WHERE trajectory_id '+objectCriteria |
| 170 queryStatement += ' ORDER BY trajectory_id, frame_number' | 171 queryStatement += ' ORDER BY trajectory_id, frame_number' |
| 171 cursor.execute(queryStatement) | |
| 172 logging.debug(queryStatement) | |
| 173 elif trajectoryType == 'object': | 172 elif trajectoryType == 'object': |
| 174 queryStatement = 'SELECT OF.object_id, P.frame_number, avg(P.x_coordinate), avg(P.y_coordinate) from '+tableName+' P, objects_features OF where P.trajectory_id = OF.trajectory_id' | 173 queryStatement = 'SELECT OF.object_id, P.frame_number, avg(P.x_coordinate), avg(P.y_coordinate) from '+tableName+' P, objects_features OF WHERE P.trajectory_id = OF.trajectory_id' |
| 175 if objectNumbers is not None: | 174 if objectNumbers is not None: |
| 176 queryStatement += ' and OF.object_id '+objectCriteria | 175 queryStatement += ' and OF.object_id '+objectCriteria |
| 177 queryStatement += ' GROUP BY OF.object_id, P.frame_number ORDER BY OF.object_id, P.frame_number' | 176 queryStatement += ' GROUP BY OF.object_id, P.frame_number ORDER BY OF.object_id, P.frame_number' |
| 178 cursor.execute(queryStatement) | |
| 179 logging.debug(queryStatement) | |
| 180 elif trajectoryType in ['bbtop', 'bbbottom']: | 177 elif trajectoryType in ['bbtop', 'bbbottom']: |
| 181 if trajectoryType == 'bbtop': | 178 if trajectoryType == 'bbtop': |
| 182 corner = 'top_left' | 179 corner = 'top_left' |
| 183 elif trajectoryType == 'bbbottom': | 180 elif trajectoryType == 'bbbottom': |
| 184 corner = 'bottom_right' | 181 corner = 'bottom_right' |
| 185 queryStatement = 'SELECT object_id, frame_number, x_'+corner+', y_'+corner+' FROM '+tableName | 182 queryStatement = 'SELECT object_id, frame_number, x_'+corner+', y_'+corner+' FROM '+tableName |
| 186 if objectNumbers is not None: | 183 if objectNumbers is not None: |
| 187 queryStatement += ' WHERE object_id '+objectCriteria | 184 queryStatement += ' WHERE object_id '+objectCriteria |
| 188 queryStatement += ' ORDER BY object_id, frame_number' | 185 queryStatement += ' ORDER BY object_id, frame_number' |
| 186 else: | |
| 187 print('no trajectory type was chosen') | |
| 188 if queryStatement is not None: | |
| 189 cursor.execute(queryStatement) | 189 cursor.execute(queryStatement) |
| 190 logging.debug(queryStatement) | 190 logging.debug(queryStatement) |
| 191 else: | |
| 192 print('no trajectory type was chosen') | |
| 193 except sqlite3.OperationalError as error: | 191 except sqlite3.OperationalError as error: |
| 194 printDBError(error) | 192 printDBError(error) |
| 195 return [] | 193 return [] |
| 196 | 194 |
| 197 objId = -1 | 195 objId = -1 |
| 218 | 216 |
| 219 def loadUserTypesFromTable(cursor, trajectoryType, objectNumbers): | 217 def loadUserTypesFromTable(cursor, trajectoryType, objectNumbers): |
| 220 objectCriteria = getObjectCriteria(objectNumbers) | 218 objectCriteria = getObjectCriteria(objectNumbers) |
| 221 queryStatement = 'SELECT object_id, road_user_type from objects' | 219 queryStatement = 'SELECT object_id, road_user_type from objects' |
| 222 if objectNumbers is not None: | 220 if objectNumbers is not None: |
| 223 queryStatement += ' where object_id '+objectCriteria | 221 queryStatement += ' WHERE object_id '+objectCriteria |
| 224 cursor.execute(queryStatement) | 222 cursor.execute(queryStatement) |
| 225 userTypes = {} | 223 userTypes = {} |
| 226 for row in cursor: | 224 for row in cursor: |
| 227 userTypes[row[0]] = row[1] | 225 userTypes[row[0]] = row[1] |
| 228 return userTypes | 226 return userTypes |
| 245 if trajectoryType == 'object': | 243 if trajectoryType == 'object': |
| 246 cursor = connection.cursor() | 244 cursor = connection.cursor() |
| 247 try: | 245 try: |
| 248 # attribute feature numbers to objects | 246 # attribute feature numbers to objects |
| 249 objectCriteria = getObjectCriteria(objectNumbers) | 247 objectCriteria = getObjectCriteria(objectNumbers) |
| 250 queryStatement = 'SELECT P.trajectory_id, OF.object_id from positions P, objects_features OF where P.trajectory_id = OF.trajectory_id' | 248 queryStatement = 'SELECT P.trajectory_id, OF.object_id from positions P, objects_features OF WHERE P.trajectory_id = OF.trajectory_id' |
| 251 if objectNumbers is not None: | 249 if objectNumbers is not None: |
| 252 queryStatement += ' and OF.object_id '+objectCriteria | 250 queryStatement += ' and OF.object_id '+objectCriteria |
| 253 queryStatement += ' group by P.trajectory_id order by OF.object_id' # order is important to group all features per object | 251 queryStatement += ' group by P.trajectory_id order by OF.object_id' # order is important to group all features per object |
| 254 cursor.execute(queryStatement) | 252 cursor.execute(queryStatement) |
| 255 logging.debug(queryStatement) | 253 logging.debug(queryStatement) |
| 393 TODO choose the interactions to load''' | 391 TODO choose the interactions to load''' |
| 394 interactions = [] | 392 interactions = [] |
| 395 connection = sqlite3.connect(filename) | 393 connection = sqlite3.connect(filename) |
| 396 cursor = connection.cursor() | 394 cursor = connection.cursor() |
| 397 try: | 395 try: |
| 398 cursor.execute('select INT.id, INT.object_id1, INT.object_id2, INT.first_frame_number, INT.last_frame_number, IND.indicator_type, IND.frame_number, IND.value from interactions INT, indicators IND where INT.id = IND.interaction_id ORDER BY INT.id, IND.indicator_type, IND.frame_number') | 396 cursor.execute('select INT.id, INT.object_id1, INT.object_id2, INT.first_frame_number, INT.last_frame_number, IND.indicator_type, IND.frame_number, IND.value from interactions INT, indicators IND WHERE INT.id = IND.interaction_id ORDER BY INT.id, IND.indicator_type, IND.frame_number') |
| 399 interactionNum = -1 | 397 interactionNum = -1 |
| 400 indicatorTypeNum = -1 | 398 indicatorTypeNum = -1 |
| 401 tmpIndicators = {} | 399 tmpIndicators = {} |
| 402 for row in cursor: | 400 for row in cursor: |
| 403 if row[0] != interactionNum: | 401 if row[0] != interactionNum: |
| 416 printDBError(error) | 414 printDBError(error) |
| 417 return [] | 415 return [] |
| 418 connection.close() | 416 connection.close() |
| 419 return interactions | 417 return interactions |
| 420 # load first and last object instants | 418 # load first and last object instants |
| 421 # CREATE TEMP TABLE IF NOT EXISTS object_instants AS SELECT OF.object_id, min(frame_number) as first_instant, max(frame_number) as last_instant from positions P, objects_features OF where P.trajectory_id = OF.trajectory_id group by OF.object_id order by OF.object_id | 419 # CREATE TEMP TABLE IF NOT EXISTS object_instants AS SELECT OF.object_id, min(frame_number) as first_instant, max(frame_number) as last_instant from positions P, objects_features OF WHERE P.trajectory_id = OF.trajectory_id group by OF.object_id order by OF.object_id |
| 422 | 420 |
| 423 def createBoundingBoxTable(filename, invHomography = None): | 421 def createBoundingBoxTable(filename, invHomography = None): |
| 424 '''Create the table to store the object bounding boxes in image space | 422 '''Create the table to store the object bounding boxes in image space |
| 425 ''' | 423 ''' |
| 426 connection = sqlite3.connect(filename) | 424 connection = sqlite3.connect(filename) |
| 427 cursor = connection.cursor() | 425 cursor = connection.cursor() |
| 428 try: | 426 try: |
| 429 cursor.execute('CREATE TABLE IF NOT EXISTS bounding_boxes (object_id INTEGER, frame_number INTEGER, x_top_left REAL, y_top_left REAL, x_bottom_right REAL, y_bottom_right REAL, PRIMARY KEY(object_id, frame_number))') | 427 cursor.execute('CREATE TABLE IF NOT EXISTS bounding_boxes (object_id INTEGER, frame_number INTEGER, x_top_left REAL, y_top_left REAL, x_bottom_right REAL, y_bottom_right REAL, PRIMARY KEY(object_id, frame_number))') |
| 430 cursor.execute('INSERT INTO bounding_boxes SELECT object_id, frame_number, min(x), min(y), max(x), max(y) from ' | 428 cursor.execute('INSERT INTO bounding_boxes SELECT object_id, frame_number, min(x), min(y), max(x), max(y) from ' |
| 431 '(SELECT object_id, frame_number, (x*{}+y*{}+{})/w as x, (x*{}+y*{}+{})/w as y from ' | 429 '(SELECT object_id, frame_number, (x*{}+y*{}+{})/w as x, (x*{}+y*{}+{})/w as y from ' |
| 432 '(SELECT OF.object_id, P.frame_number, P.x_coordinate as x, P.y_coordinate as y, P.x_coordinate*{}+P.y_coordinate*{}+{} as w from positions P, objects_features OF where P.trajectory_id = OF.trajectory_id)) '.format(invHomography[0,0], invHomography[0,1], invHomography[0,2], invHomography[1,0], invHomography[1,1], invHomography[1,2], invHomography[2,0], invHomography[2,1], invHomography[2,2])+ | 430 '(SELECT OF.object_id, P.frame_number, P.x_coordinate as x, P.y_coordinate as y, P.x_coordinate*{}+P.y_coordinate*{}+{} as w from positions P, objects_features OF WHERE P.trajectory_id = OF.trajectory_id)) '.format(invHomography[0,0], invHomography[0,1], invHomography[0,2], invHomography[1,0], invHomography[1,1], invHomography[1,2], invHomography[2,0], invHomography[2,1], invHomography[2,2])+ |
| 433 'GROUP BY object_id, frame_number') | 431 'GROUP BY object_id, frame_number') |
| 434 except sqlite3.OperationalError as error: | 432 except sqlite3.OperationalError as error: |
| 435 printDBError(error) | 433 printDBError(error) |
| 436 connection.commit() | 434 connection.commit() |
| 437 connection.close() | 435 connection.close() |
| 645 | 643 |
| 646 def setRoutes(filename, objects): | 644 def setRoutes(filename, objects): |
| 647 connection = sqlite3.connect(filename) | 645 connection = sqlite3.connect(filename) |
| 648 cursor = connection.cursor() | 646 cursor = connection.cursor() |
| 649 for obj in objects: | 647 for obj in objects: |
| 650 cursor.execute('update objects set startRouteID = {} where object_id = {}'.format(obj.startRouteID, obj.getNum())) | 648 cursor.execute('update objects set startRouteID = {} WHERE object_id = {}'.format(obj.startRouteID, obj.getNum())) |
| 651 cursor.execute('update objects set endRouteID = {} where object_id = {}'.format(obj.endRouteID, obj.getNum())) | 649 cursor.execute('update objects set endRouteID = {} WHERE object_id = {}'.format(obj.endRouteID, obj.getNum())) |
| 652 connection.commit() | 650 connection.commit() |
| 653 connection.close() | 651 connection.close() |
| 654 | 652 |
| 655 def setRoadUserTypes(filename, objects): | 653 def setRoadUserTypes(filename, objects): |
| 656 '''Saves the user types of the objects in the sqlite database stored in filename | 654 '''Saves the user types of the objects in the sqlite database stored in filename |
| 657 The objects should exist in the objects table''' | 655 The objects should exist in the objects table''' |
| 658 connection = sqlite3.connect(filename) | 656 connection = sqlite3.connect(filename) |
| 659 cursor = connection.cursor() | 657 cursor = connection.cursor() |
| 660 for obj in objects: | 658 for obj in objects: |
| 661 cursor.execute('update objects set road_user_type = {} where object_id = {}'.format(obj.getUserType(), obj.getNum())) | 659 cursor.execute('update objects set road_user_type = {} WHERE object_id = {}'.format(obj.getUserType(), obj.getNum())) |
| 662 connection.commit() | 660 connection.commit() |
| 663 connection.close() | 661 connection.close() |
| 664 | 662 |
| 665 ######################### | 663 ######################### |
| 666 # txt files | 664 # txt files |
| 731 else: return self.fp.readline() | 729 else: return self.fp.readline() |
| 732 | 730 |
| 733 def generatePDLaneColumn(data): | 731 def generatePDLaneColumn(data): |
| 734 data['LANE'] = data['LANE\LINK\NO'].astype(str)+'_'+data['LANE\INDEX'].astype(str) | 732 data['LANE'] = data['LANE\LINK\NO'].astype(str)+'_'+data['LANE\INDEX'].astype(str) |
| 735 | 733 |
| 736 def loadTrajectoriesFromVissimFile(filename, simulationStepsPerTimeUnit, nObjects = -1, warmUpLastInstant = None, usePandas = False, nDecimals = 2, lowMemory = True): | 734 def convertTrajectoriesVissimToSqlite(filename): |
| 735 '''Relies on a system call to sqlite3 | |
| 736 sqlite3 [file.sqlite] < import_fzp.sql''' | |
| 737 sqlScriptFilename = "import_fzp.sql" | |
| 738 # create sql file | |
| 739 out = openCheck(sqlScriptFilename, "w") | |
| 740 out.write(".separator \";\"\n"+ | |
| 741 "CREATE TABLE IF NOT EXISTS curvilinear_positions (t REAL, trajectory_id INTEGER, link_id INTEGER, lane_id INTEGER, s_coordinate REAL, y_coordinate REAL, speed REAL, PRIMARY KEY (t, trajectory_id));\n"+ | |
| 742 ".import "+filename+" curvilinear_positions\n"+ | |
| 743 "DELETE FROM curvilinear_positions WHERE trajectory_id IS NULL OR trajectory_id = \"NO\";\n") | |
| 744 out.close() | |
| 745 # system call | |
| 746 from os import system, remove | |
| 747 system("sqlite3 "+utils.removeExtension(filename)+".sqlite < "+sqlScriptFilename) | |
| 748 remove(sqlScriptFilename) | |
| 749 | |
| 750 def loadTrajectoriesFromVissimFile(filename, simulationStepsPerTimeUnit, objectNumbers = None, warmUpLastInstant = None, usePandas = False, nDecimals = 2, lowMemory = True): | |
| 737 '''Reads data from VISSIM .fzp trajectory file | 751 '''Reads data from VISSIM .fzp trajectory file |
| 738 simulationStepsPerTimeUnit is the number of simulation steps per unit of time used by VISSIM | 752 simulationStepsPerTimeUnit is the number of simulation steps per unit of time used by VISSIM |
| 739 for example, there seems to be 5 simulation steps per simulated second in VISSIM, | 753 for example, there seems to be 5 simulation steps per simulated second in VISSIM, |
| 740 so simulationStepsPerTimeUnit should be 5, | 754 so simulationStepsPerTimeUnit should be 5, |
| 741 so that all times correspond to the number of the simulation step (and can be stored as integers) | 755 so that all times correspond to the number of the simulation step (and can be stored as integers) |
| 759 objNum = int(row['NO']) | 773 objNum = int(row['NO']) |
| 760 tmp = data[data['NO'] == objNum] | 774 tmp = data[data['NO'] == objNum] |
| 761 objects[objNum] = moving.MovingObject(num = objNum, timeInterval = moving.TimeInterval(row['first'], row['last'])) | 775 objects[objNum] = moving.MovingObject(num = objNum, timeInterval = moving.TimeInterval(row['first'], row['last'])) |
| 762 # positions should be rounded to nDecimals decimals only | 776 # positions should be rounded to nDecimals decimals only |
| 763 objects[objNum].curvilinearPositions = moving.CurvilinearTrajectory(S = npround(tmp['POS'].tolist(), nDecimals), Y = npround(tmp['POSLAT'].tolist(), nDecimals), lanes = tmp['LANE'].tolist()) | 777 objects[objNum].curvilinearPositions = moving.CurvilinearTrajectory(S = npround(tmp['POS'].tolist(), nDecimals), Y = npround(tmp['POSLAT'].tolist(), nDecimals), lanes = tmp['LANE'].tolist()) |
| 764 if nObjects > 0 and len(objects) >= nObjects: | 778 if objectNumbers is not None and objectNumbers > 0 and len(objects) >= objectNumbers: |
| 765 break | 779 break |
| 766 return objects.values() | 780 return objects.values() |
| 767 else: | 781 else: |
| 768 inputfile = openCheck(filename, quitting = True) | 782 if filename.endswith(".fzp"): |
| 769 # data = pd.read_csv(filename, skiprows=15, delimiter=';') | 783 inputfile = openCheck(filename, quitting = True) |
| 770 # skip header: 15 lines + 1 | |
| 771 line = readline(inputfile, '*$') | |
| 772 while len(line) > 0:#for line in inputfile: | |
| 773 data = line.strip().split(';') | |
| 774 objNum = int(data[1]) | |
| 775 instant = int(float(data[0])*simulationStepsPerTimeUnit) | |
| 776 s = float(data[4]) | |
| 777 y = float(data[5]) | |
| 778 lane = data[2]+'_'+data[3] | |
| 779 if objNum not in objects: | |
| 780 if warmUpLastInstant is None or instant >= warmUpLastInstant: | |
| 781 if nObjects < 0 or len(objects) < nObjects: | |
| 782 objects[objNum] = moving.MovingObject(num = objNum, timeInterval = moving.TimeInterval(instant, instant)) | |
| 783 objects[objNum].curvilinearPositions = moving.CurvilinearTrajectory() | |
| 784 if (warmUpLastInstant is None or instant >= warmUpLastInstant) and objNum in objects: | |
| 785 objects[objNum].timeInterval.last = instant | |
| 786 objects[objNum].curvilinearPositions.addPositionSYL(s, y, lane) | |
| 787 line = readline(inputfile, '*$') | 784 line = readline(inputfile, '*$') |
| 788 | 785 while len(line) > 0:#for line in inputfile: |
| 789 return objects.values() | 786 data = line.strip().split(';') |
| 787 objNum = int(data[1]) | |
| 788 instant = float(data[0])*simulationStepsPerTimeUnit | |
| 789 s = float(data[4]) | |
| 790 y = float(data[5]) | |
| 791 lane = data[2]+'_'+data[3] | |
| 792 if objNum not in objects: | |
| 793 if warmUpLastInstant is None or instant >= warmUpLastInstant: | |
| 794 if objectNumbers is None or len(objects) < objectNumbers: | |
| 795 objects[objNum] = moving.MovingObject(num = objNum, timeInterval = moving.TimeInterval(instant, instant)) | |
| 796 objects[objNum].curvilinearPositions = moving.CurvilinearTrajectory() | |
| 797 if (warmUpLastInstant is None or instant >= warmUpLastInstant) and objNum in objects: | |
| 798 objects[objNum].timeInterval.last = instant | |
| 799 objects[objNum].curvilinearPositions.addPositionSYL(s, y, lane) | |
| 800 line = readline(inputfile, '*$') | |
| 801 return objects.values() | |
| 802 elif filename.endswith(".sqlite"): | |
| 803 connection = sqlite3.connect(filename) | |
| 804 cursor = connection.cursor() | |
| 805 queryStatement = 'SELECT t, trajectory_id, link_id, lane_id, s_coordinate, y_coordinate FROM curvilinear_positions' | |
| 806 if objectNumbers is not None: | |
| 807 queryStatement += ' WHERE trajectory_id '+getObjectCriteria(objectNumbers) | |
| 808 queryStatement += ' ORDER BY trajectory_id, t' | |
| 809 #objects = loadTrajectoriesFromTable(connection, "curvilinear_positions", "vissim_curvilinear", objectNumbers) | |
| 810 for row in cursor: | |
| 811 objNum = row[1] | |
| 812 instant = row[0]*simulationStepsPerTimeUnit | |
| 813 s = row[4] | |
| 814 y = row[5] | |
| 815 lane = '{}_{}'.format(row[2], row[3]) | |
| 816 if objNum not in objects: | |
| 817 if warmUpLastInstant is None or instant >= warmUpLastInstant: | |
| 818 if objectNumbers is None or len(objects) < objectNumbers: | |
| 819 objects[objNum] = moving.MovingObject(num = objNum, timeInterval = moving.TimeInterval(instant, instant)) | |
| 820 objects[objNum].curvilinearPositions = moving.CurvilinearTrajectory() | |
| 821 if (warmUpLastInstant is None or instant >= warmUpLastInstant) and objNum in objects: | |
| 822 objects[objNum].timeInterval.last = instant | |
| 823 objects[objNum].curvilinearPositions.addPositionSYL(s, y, lane) | |
| 824 else: | |
| 825 print("File type of "+filename+" not supported (only .sqlite and .fzp files)") | |
| 826 | |
| 790 | 827 |
| 791 def selectPDLanes(data, lanes = None): | 828 def selectPDLanes(data, lanes = None): |
| 792 '''Selects the subset of data for the right lanes | 829 '''Selects the subset of data for the right lanes |
| 793 | 830 |
| 794 Lane format is a string 'x_y' where x is link index and y is lane index''' | 831 Lane format is a string 'x_y' where x is link index and y is lane index''' |
