comparison python/storage.py @ 649:df9ddeaee4a6

added ability to select lanes to count collisions or stationary vehicles in VISSIM files
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Thu, 16 Apr 2015 11:34:51 +0200
parents 458890c0437c
children 994dd644f6ab
comparison
equal deleted inserted replaced
648:da665302c88d 649:df9ddeaee4a6
637 if self.sechead: 637 if self.sechead:
638 try: return self.sechead 638 try: return self.sechead
639 finally: self.sechead = None 639 finally: self.sechead = None
640 else: return self.fp.readline() 640 else: return self.fp.readline()
641 641
642 def generatePDLaneColumn(data):
643 data['LANE'] = data['LANE\LINK\NO'].astype(str)+'_'+data['LANE\INDEX'].astype(str)
644
642 def loadTrajectoriesFromVissimFile(filename, simulationStepsPerTimeUnit, nObjects = -1, warmUpLastInstant = None, usePandas = False, nDecimals = 2): 645 def loadTrajectoriesFromVissimFile(filename, simulationStepsPerTimeUnit, nObjects = -1, warmUpLastInstant = None, usePandas = False, nDecimals = 2):
643 '''Reads data from VISSIM .fzp trajectory file 646 '''Reads data from VISSIM .fzp trajectory file
644 simulationStepsPerTimeUnit is the number of simulation steps per unit of time used by VISSIM 647 simulationStepsPerTimeUnit is the number of simulation steps per unit of time used by VISSIM
645 for example, there seems to be 5 simulation steps per simulated second in VISSIM, 648 for example, there seems to be 5 simulation steps per simulated second in VISSIM,
646 so simulationStepsPerTimeUnit should be 5, 649 so simulationStepsPerTimeUnit should be 5,
651 654
652 if usePandas: 655 if usePandas:
653 from pandas import read_csv 656 from pandas import read_csv
654 from numpy import min, max, round 657 from numpy import min, max, round
655 data = read_csv(filename, delimiter=';', comment='*', header=0, skiprows = 1) 658 data = read_csv(filename, delimiter=';', comment='*', header=0, skiprows = 1)
656 data['LANE'] = data['LANE\LINK\NO'].astype(str)+'_'+data['LANE\INDEX'].astype(str) 659 generatePDLaneColumn(data)
657 data['TIME'] = data['$VEHICLE:SIMSEC']*simulationStepsPerTimeUnit 660 data['TIME'] = data['$VEHICLE:SIMSEC']*simulationStepsPerTimeUnit
658 grouped = data.loc[:,['NO','TIME']].groupby(['NO'], as_index = False) 661 grouped = data.loc[:,['NO','TIME']].groupby(['NO'], as_index = False)
659 instants = grouped['TIME'].agg({'first': min, 'last': max}) 662 instants = grouped['TIME'].agg({'first': min, 'last': max})
660 if warmUpLastInstant is not None: 663 if warmUpLastInstant is not None:
661 instants = instants[instants['first'] >= warmUpLastInstant] 664 instants = instants[instants['first'] >= warmUpLastInstant]
690 objects[objNum].curvilinearPositions.addPositionSYL(s, y, lane) 693 objects[objNum].curvilinearPositions.addPositionSYL(s, y, lane)
691 line = readline(inputfile, '*$') 694 line = readline(inputfile, '*$')
692 695
693 return objects.values() 696 return objects.values()
694 697
695 def countStoppedVehiclesVissim(filename, proportionStationaryTime = 0.7): 698 def selectPDLanes(data, lanes = None):
699 '''Selects the subset of data for the right lanes
700
701 Lane format is a string 'x_y' where x is link index and y is lane index'''
702 if lanes is not None:
703 if 'LANE' not in data.columns:
704 generatePDLaneColumn(data)
705 indices = (data['LANE'] == lanes[0])
706 for l in lanes[1:]:
707 indices = indices | (data['LANE'] == l)
708 return data[indices]
709 else:
710 return data
711
712 def countStoppedVehiclesVissim(filename, lanes = None, proportionStationaryTime = 0.7):
696 '''Counts the number of vehicles stopped for a long time in a VISSIM trajectory file 713 '''Counts the number of vehicles stopped for a long time in a VISSIM trajectory file
697 and the total number of vehicles 714 and the total number of vehicles
698 715
699 Vehicles are considered finally stationary 716 Vehicles are considered finally stationary
700 if more than proportionStationaryTime of their total time''' 717 if more than proportionStationaryTime of their total time
718 If lanes is not None, only the data for the selected lanes will be provided
719 (format as string x_y where x is link index and y is lane index)'''
701 from pandas import read_csv 720 from pandas import read_csv
702 from numpy import array, sum as npsum 721 from numpy import array, sum as npsum
703 data = read_csv(filename, delimiter=';', comment='*', header=0, skiprows = 1, usecols = ['NO', '$VEHICLE:SIMSEC', 'POS']) # 'LANE\LINK\NO', 'LANE\INDEX', 722 columns = ['NO', '$VEHICLE:SIMSEC', 'POS']
723 if lanes is not None:
724 columns += ['LANE\LINK\NO', 'LANE\INDEX']
725 data = read_csv(filename, delimiter=';', comment='*', header=0, skiprows = 1, usecols = columns)
726 data = selectPDLanes(data, lanes)
704 data.sort(['$VEHICLE:SIMSEC'], inplace = True) 727 data.sort(['$VEHICLE:SIMSEC'], inplace = True)
705 #merged = merge(data, data, how='inner', left_on=['LANE\LINK\NO', 'LANE\INDEX', '$VEHICLE:SIMSEC'], right_on=['LANE\LINK\NO', 'LANE\INDEX', '$VEHICLE:SIMSEC'], sort = False)
706 #merged = merged[merged['NO_x']>merged['NO_y']]
707 728
708 nStationary = 0 729 nStationary = 0
709 from matplotlib.pyplot import plot, figure 730 from matplotlib.pyplot import plot, figure
710 nVehicles = 0 731 nVehicles = 0
711 for name, group in data.groupby(['NO'], sort = False): 732 for name, group in data.groupby(['NO'], sort = False):
715 if npsum(diff == 0.) >= proportionStationaryTime*len(positions): 736 if npsum(diff == 0.) >= proportionStationaryTime*len(positions):
716 nStationary += 1 737 nStationary += 1
717 738
718 return nStationary, nVehicles 739 return nStationary, nVehicles
719 740
720 def countCollisionsVissim(filename, collisionTimeDifference = 0.2): 741 def countCollisionsVissim(filename, lanes = None, collisionTimeDifference = 0.2):
721 '''Counts the number of collisions per lane in a VISSIM trajectory file 742 '''Counts the number of collisions per lane in a VISSIM trajectory file
722 743
723 To distinguish between cars passing and collision, 744 To distinguish between cars passing and collision,
724 one checks when the sign of the position difference inverts 745 one checks when the sign of the position difference inverts
725 (if the time are closer than collisionTimeDifference)''' 746 (if the time are closer than collisionTimeDifference)
747 If lanes is not None, only the data for the selected lanes will be provided
748 (format as string x_y where x is link index and y is lane index)'''
726 from pandas import read_csv, merge 749 from pandas import read_csv, merge
727 data = read_csv(filename, delimiter=';', comment='*', header=0, skiprows = 1, usecols = ['LANE\LINK\NO', 'LANE\INDEX', '$VEHICLE:SIMSEC', 'NO', 'POS']) 750 data = read_csv(filename, delimiter=';', comment='*', header=0, skiprows = 1, usecols = ['LANE\LINK\NO', 'LANE\INDEX', '$VEHICLE:SIMSEC', 'NO', 'POS'])
751 data = selectPDLanes(data, lanes)
728 merged = merge(data, data, how='inner', left_on=['LANE\LINK\NO', 'LANE\INDEX', '$VEHICLE:SIMSEC'], right_on=['LANE\LINK\NO', 'LANE\INDEX', '$VEHICLE:SIMSEC'], sort = False) 752 merged = merge(data, data, how='inner', left_on=['LANE\LINK\NO', 'LANE\INDEX', '$VEHICLE:SIMSEC'], right_on=['LANE\LINK\NO', 'LANE\INDEX', '$VEHICLE:SIMSEC'], sort = False)
729 merged = merged[merged['NO_x']>merged['NO_y']] 753 merged = merged[merged['NO_x']>merged['NO_y']]
730 754
731 nCollisions = 0 755 nCollisions = 0
732 for name, group in merged.groupby(['LANE\LINK\NO', 'LANE\INDEX', 'NO_x', 'NO_y']): 756 for name, group in merged.groupby(['LANE\LINK\NO', 'LANE\INDEX', 'NO_x', 'NO_y']):