comparison trafficintelligence/storage.py @ 1030:aafbc0bab925

moved method around to avoid cross-dependencies
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Tue, 19 Jun 2018 10:04:52 -0400
parents cc5cb04b04b0
children 8ffb3ae9f3d2
comparison
equal deleted inserted replaced
1029:c6cf75a2ed08 1030:aafbc0bab925
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
5 from trafficintelligence import utils, moving, events, indicators
6 from trafficintelligence.base import VideoFilenameAddable
7 4
8 from pathlib import Path 5 from pathlib import Path
9 import shutil 6 import shutil
10 from copy import copy 7 from copy import copy
11 import sqlite3, logging 8 import sqlite3, logging
9
12 from numpy import log, min as npmin, max as npmax, round as npround, array, sum as npsum, loadtxt, floor as npfloor, ceil as npceil, linalg 10 from numpy import log, min as npmin, max as npmax, round as npround, array, sum as npsum, loadtxt, floor as npfloor, ceil as npceil, linalg
13 from pandas import read_csv, merge 11 from pandas import read_csv, merge
14 12
15 13 from trafficintelligence import utils, moving, events, indicators
16 commentChar = '#' 14 from trafficintelligence.base import VideoFilenameAddable
17 15
18 delimiterChar = '%';
19 16
20 ngsimUserTypes = {'twowheels':1, 17 ngsimUserTypes = {'twowheels':1,
21 'car':2, 18 'car':2,
22 'truck':3} 19 'truck':3}
23 20
879 876
880 ######################### 877 #########################
881 # txt files 878 # txt files
882 ######################### 879 #########################
883 880
884 def openCheck(filename, option = 'r', quitting = False):
885 '''Open file filename in read mode by default
886 and checks it is open'''
887 try:
888 return open(filename, option)
889 except IOError:
890 print('File {} could not be opened.'.format(filename))
891 if quitting:
892 from sys import exit
893 exit()
894 return None
895
896 def readline(f, commentCharacters = commentChar):
897 '''Modified readline function to skip comments
898 Can take a list of characters or a string (in will work in both)'''
899 s = f.readline()
900 while (len(s) > 0) and s[0] in commentCharacters:
901 s = f.readline()
902 return s.strip()
903
904 def getLines(f, delimiterChar = delimiterChar, commentCharacters = commentChar):
905 '''Gets a complete entry (all the lines) in between delimiterChar.'''
906 dataStrings = []
907 s = readline(f, commentCharacters)
908 while len(s) > 0 and s[0] != delimiterChar:
909 dataStrings += [s.strip()]
910 s = readline(f, commentCharacters)
911 return dataStrings
912
913 def saveList(filename, l): 881 def saveList(filename, l):
914 f = openCheck(filename, 'w') 882 f = utils.openCheck(filename, 'w')
915 for x in l: 883 for x in l:
916 f.write('{}\n'.format(x)) 884 f.write('{}\n'.format(x))
917 f.close() 885 f.close()
918 886
919 def loadListStrings(filename, commentCharacters = commentChar): 887 def loadListStrings(filename, commentCharacters = utils.commentChar):
920 f = openCheck(filename, 'r') 888 f = utils.openCheck(filename, 'r')
921 result = getLines(f, commentCharacters) 889 result = utils.getLines(f, commentCharacters)
922 f.close() 890 f.close()
923 return result 891 return result
924 892
925 def getValuesFromINIFile(filename, option, delimiterChar = '=', commentCharacters = commentChar): 893 def getValuesFromINIFile(filename, option, delimiterChar = '=', commentCharacters = utils.commentChar):
926 values = [] 894 values = []
927 for l in loadListStrings(filename, commentCharacters): 895 for l in loadListStrings(filename, commentCharacters):
928 if l.startswith(option): 896 if l.startswith(option):
929 values.append(l.split(delimiterChar)[1].strip()) 897 values.append(l.split(delimiterChar)[1].strip())
930 return values 898 return values
940 yield line 908 yield line
941 909
942 def loadPemsTraffic(filename): 910 def loadPemsTraffic(filename):
943 '''Loads traffic data downloaded from the http://pems.dot.ca.gov clearinghouse 911 '''Loads traffic data downloaded from the http://pems.dot.ca.gov clearinghouse
944 into pandas dataframe''' 912 into pandas dataframe'''
945 f = openCheck(filename) 913 f = utils.openCheck(filename)
946 l = f.readline().strip() 914 l = f.readline().strip()
947 items = l.split(',') 915 items = l.split(',')
948 headers = ['time', 'station', 'district', 'route', 'direction', 'lanetype', 'length', 'nsamples', 'pctobserved', 'flow', 'occupancy', 'speed', 'delay35', 'delay40', 'delay45', 'delay50', 'delay55', 'delay60'] 916 headers = ['time', 'station', 'district', 'route', 'direction', 'lanetype', 'length', 'nsamples', 'pctobserved', 'flow', 'occupancy', 'speed', 'delay35', 'delay40', 'delay45', 'delay50', 'delay55', 'delay60']
949 nLanes = (len(items)-len(headers))/3 917 nLanes = (len(items)-len(headers))/3
950 for i in range(nLanes): 918 for i in range(nLanes):
958 def convertTrajectoriesVissimToSqlite(filename): 926 def convertTrajectoriesVissimToSqlite(filename):
959 '''Relies on a system call to sqlite3 927 '''Relies on a system call to sqlite3
960 sqlite3 [file.sqlite] < import_fzp.sql''' 928 sqlite3 [file.sqlite] < import_fzp.sql'''
961 sqlScriptFilename = "import_fzp.sql" 929 sqlScriptFilename = "import_fzp.sql"
962 # create sql file 930 # create sql file
963 out = openCheck(sqlScriptFilename, "w") 931 out = utils.openCheck(sqlScriptFilename, "w")
964 out.write(".separator \";\"\n"+ 932 out.write(".separator \";\"\n"+
965 "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"+ 933 "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"+
966 ".import "+filename+" curvilinear_positions\n"+ 934 ".import "+filename+" curvilinear_positions\n"+
967 "DELETE FROM curvilinear_positions WHERE trajectory_id IS NULL OR trajectory_id = \"NO\";\n") 935 "DELETE FROM curvilinear_positions WHERE trajectory_id IS NULL OR trajectory_id = \"NO\";\n")
968 out.close() 936 out.close()
969 # system call 937 # system call
970 from subprocess import run 938 from subprocess import run
971 out = openCheck("err.log", "w") 939 out = utils.openCheck("err.log", "w")
972 run("sqlite3 "+utils.removeExtension(filename)+".sqlite < "+sqlScriptFilename, stderr = out) 940 run("sqlite3 "+utils.removeExtension(filename)+".sqlite < "+sqlScriptFilename, stderr = out)
973 out.close() 941 out.close()
974 shutil.os.remove(sqlScriptFilename) 942 shutil.os.remove(sqlScriptFilename)
975 943
976 def loadObjectNumbersInLinkFromVissimFile(filename, linkIds): 944 def loadObjectNumbersInLinkFromVissimFile(filename, linkIds):
1025 objects[objNum].curvilinearPositions = moving.CurvilinearTrajectory(S = npround(tmp['POS'].tolist(), nDecimals), Y = npround(tmp['POSLAT'].tolist(), nDecimals), lanes = tmp['LANE'].tolist()) 993 objects[objNum].curvilinearPositions = moving.CurvilinearTrajectory(S = npround(tmp['POS'].tolist(), nDecimals), Y = npround(tmp['POSLAT'].tolist(), nDecimals), lanes = tmp['LANE'].tolist())
1026 if objectNumbers is not None and objectNumbers > 0 and len(objects) >= objectNumbers: 994 if objectNumbers is not None and objectNumbers > 0 and len(objects) >= objectNumbers:
1027 return list(objects.values()) 995 return list(objects.values())
1028 else: 996 else:
1029 if filename.endswith(".fzp"): 997 if filename.endswith(".fzp"):
1030 inputfile = openCheck(filename, quitting = True) 998 inputfile = utils.openCheck(filename, quitting = True)
1031 line = readline(inputfile, '*$') 999 line = utils.readline(inputfile, '*$')
1032 while len(line) > 0:#for line in inputfile: 1000 while len(line) > 0:#for line in inputfile:
1033 data = line.strip().split(';') 1001 data = line.strip().split(';')
1034 objNum = int(data[1]) 1002 objNum = int(data[1])
1035 instant = float(data[0])*simulationStepsPerTimeUnit 1003 instant = float(data[0])*simulationStepsPerTimeUnit
1036 s = float(data[4]) 1004 s = float(data[4])
1042 objects[objNum] = moving.MovingObject(num = objNum, timeInterval = moving.TimeInterval(instant, instant)) 1010 objects[objNum] = moving.MovingObject(num = objNum, timeInterval = moving.TimeInterval(instant, instant))
1043 objects[objNum].curvilinearPositions = moving.CurvilinearTrajectory() 1011 objects[objNum].curvilinearPositions = moving.CurvilinearTrajectory()
1044 if (warmUpLastInstant is None or instant >= warmUpLastInstant) and objNum in objects: 1012 if (warmUpLastInstant is None or instant >= warmUpLastInstant) and objNum in objects:
1045 objects[objNum].timeInterval.last = instant 1013 objects[objNum].timeInterval.last = instant
1046 objects[objNum].curvilinearPositions.addPositionSYL(s, y, lane) 1014 objects[objNum].curvilinearPositions.addPositionSYL(s, y, lane)
1047 line = readline(inputfile, '*$') 1015 line = utils.readline(inputfile, '*$')
1048 elif filename.endswith(".sqlite"): 1016 elif filename.endswith(".sqlite"):
1049 with sqlite3.connect(filename) as connection: 1017 with sqlite3.connect(filename) as connection:
1050 cursor = connection.cursor() 1018 cursor = connection.cursor()
1051 queryStatement = 'SELECT t, trajectory_id, link_id, lane_id, s_coordinate, y_coordinate FROM curvilinear_positions' 1019 queryStatement = 'SELECT t, trajectory_id, link_id, lane_id, s_coordinate, y_coordinate FROM curvilinear_positions'
1052 if objectNumbers is not None: 1020 if objectNumbers is not None:
1154 def loadTrajectoriesFromNgsimFile(filename, nObjects = -1, sequenceNum = -1): 1122 def loadTrajectoriesFromNgsimFile(filename, nObjects = -1, sequenceNum = -1):
1155 '''Reads data from the trajectory data provided by NGSIM project 1123 '''Reads data from the trajectory data provided by NGSIM project
1156 and returns the list of Feature objects''' 1124 and returns the list of Feature objects'''
1157 objects = [] 1125 objects = []
1158 1126
1159 inputfile = openCheck(filename, quitting = True) 1127 inputfile = utils.openCheck(filename, quitting = True)
1160 1128
1161 def createObject(numbers): 1129 def createObject(numbers):
1162 firstFrameNum = int(numbers[1]) 1130 firstFrameNum = int(numbers[1])
1163 # do the geometry and usertype 1131 # do the geometry and usertype
1164 1132
1178 obj.curvilinearPositions = moving.CurvilinearTrajectory([float(numbers[5])],[float(numbers[4])], obj.laneNums) # X is the longitudinal coordinate 1146 obj.curvilinearPositions = moving.CurvilinearTrajectory([float(numbers[5])],[float(numbers[4])], obj.laneNums) # X is the longitudinal coordinate
1179 obj.speeds = [float(numbers[11])] 1147 obj.speeds = [float(numbers[11])]
1180 obj.size = [float(numbers[8]), float(numbers[9])] # 8 lengh, 9 width # TODO: temporary, should use a geometry object 1148 obj.size = [float(numbers[8]), float(numbers[9])] # 8 lengh, 9 width # TODO: temporary, should use a geometry object
1181 return obj 1149 return obj
1182 1150
1183 numbers = readline(inputfile).strip().split() 1151 numbers = utils.readline(inputfile).strip().split()
1184 if (len(numbers) > 0): 1152 if (len(numbers) > 0):
1185 obj = createObject(numbers) 1153 obj = createObject(numbers)
1186 1154
1187 for line in inputfile: 1155 for line in inputfile:
1188 numbers = line.strip().split() 1156 numbers = line.strip().split()
1216 1184
1217 def convertNgsimFile(inputfile, outputfile, append = False, nObjects = -1, sequenceNum = 0): 1185 def convertNgsimFile(inputfile, outputfile, append = False, nObjects = -1, sequenceNum = 0):
1218 '''Reads data from the trajectory data provided by NGSIM project 1186 '''Reads data from the trajectory data provided by NGSIM project
1219 and converts to our current format.''' 1187 and converts to our current format.'''
1220 if append: 1188 if append:
1221 out = openCheck(outputfile,'a') 1189 out = utils.openCheck(outputfile,'a')
1222 else: 1190 else:
1223 out = openCheck(outputfile,'w') 1191 out = utils.openCheck(outputfile,'w')
1224 nObjectsPerType = [0,0,0] 1192 nObjectsPerType = [0,0,0]
1225 1193
1226 features = loadNgsimFile(inputfile, sequenceNum) 1194 features = loadNgsimFile(inputfile, sequenceNum)
1227 for f in features: 1195 for f in features:
1228 nObjectsPerType[f.userType-1] += 1 1196 nObjectsPerType[f.userType-1] += 1
1235 def loadPinholeCameraModel(filename, tanalystFormat = True): 1203 def loadPinholeCameraModel(filename, tanalystFormat = True):
1236 '''Loads the data from a file containing the camera parameters 1204 '''Loads the data from a file containing the camera parameters
1237 (pinhole camera model, http://docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html) 1205 (pinhole camera model, http://docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html)
1238 and returns a dictionary''' 1206 and returns a dictionary'''
1239 if tanalystFormat: 1207 if tanalystFormat:
1240 f = openCheck(filename, quitting = True) 1208 f = utils.openCheck(filename, quitting = True)
1241 content = getLines(f) 1209 content = utils.getLines(f)
1242 cameraData = {} 1210 cameraData = {}
1243 for l in content: 1211 for l in content:
1244 tmp = l.split(':') 1212 tmp = l.split(':')
1245 cameraData[tmp[0]] = float(tmp[1].strip().replace(',','.')) 1213 cameraData[tmp[0]] = float(tmp[1].strip().replace(',','.'))
1246 return cameraData 1214 return cameraData
1259 p2 = curvilinearPositions[i] 1227 p2 = curvilinearPositions[i]
1260 s += ',{},{}'.format(p2[0],p2[1]) 1228 s += ',{},{}'.format(p2[0],p2[1])
1261 f.write(s+'\n') 1229 f.write(s+'\n')
1262 1230
1263 def saveTrajectoriesToCsv(filename, objects): 1231 def saveTrajectoriesToCsv(filename, objects):
1264 f = openCheck(filename, 'w') 1232 f = utils.openCheck(filename, 'w')
1265 for i,obj in enumerate(objects): 1233 for i,obj in enumerate(objects):
1266 savePositionsToCsv(f, obj) 1234 savePositionsToCsv(f, obj)
1267 f.close() 1235 f.close()
1268 1236
1269 1237
1275 'Class for the parameters of object classifiers' 1243 'Class for the parameters of object classifiers'
1276 def loadConfigFile(self, filename): 1244 def loadConfigFile(self, filename):
1277 from configparser import ConfigParser 1245 from configparser import ConfigParser
1278 1246
1279 config = ConfigParser() 1247 config = ConfigParser()
1280 config.read_file(addSectionHeader(openCheck(filename))) 1248 config.read_file(addSectionHeader(utils.openCheck(filename)))
1281 1249
1282 parentPath = Path(filename).parent 1250 parentPath = Path(filename).parent
1283 self.sectionHeader = config.sections()[0] 1251 self.sectionHeader = config.sections()[0]
1284 1252
1285 self.pedBikeCarSVMFilename = utils.getRelativeFilename(parentPath, config.get(self.sectionHeader, 'pbv-svm-filename')) 1253 self.pedBikeCarSVMFilename = utils.getRelativeFilename(parentPath, config.get(self.sectionHeader, 'pbv-svm-filename'))
1344 1312
1345 def loadConfigFile(self, filename): 1313 def loadConfigFile(self, filename):
1346 from configparser import ConfigParser 1314 from configparser import ConfigParser
1347 1315
1348 config = ConfigParser(strict=False) 1316 config = ConfigParser(strict=False)
1349 config.read_file(addSectionHeader(openCheck(filename))) 1317 config.read_file(addSectionHeader(utils.openCheck(filename)))
1350 1318
1351 parentPath = Path(filename).parent 1319 parentPath = Path(filename).parent
1352 self.sectionHeader = config.sections()[0] 1320 self.sectionHeader = config.sections()[0]
1353 # Tracking/display parameters 1321 # Tracking/display parameters
1354 self.videoFilename = utils.getRelativeFilename(parentPath, config.get(self.sectionHeader, 'video-filename')) 1322 self.videoFilename = utils.getRelativeFilename(parentPath, config.get(self.sectionHeader, 'video-filename'))
1460 1428
1461 @staticmethod 1429 @staticmethod
1462 def loadConfigFile(filename): 1430 def loadConfigFile(filename):
1463 from configparser import ConfigParser 1431 from configparser import ConfigParser
1464 config = ConfigParser() 1432 config = ConfigParser()
1465 config.readfp(openCheck(filename)) 1433 config.readfp(utils.openCheck(filename))
1466 configDict = dict() 1434 configDict = dict()
1467 for sectionName in config.sections(): 1435 for sectionName in config.sections():
1468 configDict[sectionName] = SceneParameters(config, sectionName) 1436 configDict[sectionName] = SceneParameters(config, sectionName)
1469 return configDict 1437 return configDict
1470 1438