Mercurial > hg > nsaunier > traffic-intelligence
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']): |
