-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathGFSVis.py
276 lines (245 loc) · 14.4 KB
/
GFSVis.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# Script for visualizing a grid file sequence
import GridFileSequence as GFS
import numpy as np
import os
import pygame
from primitives import Vector2
import ColorMap
from trajectory import loadTrajectory
def drawSites( sites, surface, grid, radius=3 ):
'''Draws dots at the site locations onto the provided surface.
@param sites An Nx2 numpy array of locations in world coordinates.
@param surface An instance of a pygame Surface. The sites will be
drawn onto this surface.
@param grid An instance of AbstractGrid (see Grid.py) Used to map
from world to image coordinates.
@param radius A float. The radius of the sites (in pixels)
'''
RADIUS = 3
for site in sites:
x, y = grid.getCenter( Vector2( site[0], site[1] ) )
y = grid.resolution[1] - y
pygame.draw.circle( surface, (0,0,0), (x,y), radius + 2 )
pygame.draw.circle( surface, (255, 255, 255), (x,y), radius )
def drawObstacles( obstacles, surface, grid ):
'''Draws an obstacle on the a surface using the grid as the translation from
world to image coordsinates.
@param obstacles An instance of ObstacleSet (see obstacles.py)
@param surface An instance of a pygame surface. The obstacles will
be drawn on this surface.
@param grid An instance of AbstractGrid (see Grid.py). Used to map
from world to image coordinates.
'''
OBST_COLOR = np.array( (128,128,128), dtype=np.uint8 )
OBST_WIDTH = 1
for obst in obstacles.polys:
if ( obst.closed ):
verts = map( lambda x: grid.getCenter( Vector2( x[0], x[1] ) ), obst.vertices )
pygame.draw.polygon( surface, OBST_COLOR, verts )
else:
for seg in obst.segments:
p0 = grid.getCenter( Vector2( seg.p1[0], seg.p1[1] ) )
p1 = grid.getCenter( Vector2( seg.p2[0], seg.p2[1] ) )
pygame.draw.line( surface, OBST_COLOR, (p0[0],p0[1]), (p1[0], p1[1]), OBST_WIDTH )
def visualizeGrid( grid, cMap, outFileName, minVal, maxVal, sites=None, obstacles=None ):
'''Visualizes a grid file sequence with the given color map.
@param grid An instance of a DataGrid. A single grid to visualize.
@param cMap An instance of ColorMap. Indicates how the visualization works.
@param outFileName A string. The name of the file to save the image as. The path to the
file must already exist.
@param minVal A float. The minimum value used for the color map
@param maxVal A float. The maximum value used for the color map
@param sites An Nx2 numpy array of locations in world coordinates.
@param obstacles An instance of ObstacleSet (optional). If obstacle are provided,
Then they will be drawn over the top of the data.
'''
s = grid.surface( cMap, minVal, maxVal )
if ( not sites is None ):
drawSites( sites, s, grid )
if ( not obstacles is None ):
drawObstacles( obstacles, s, grid )
pygame.image.save( s, outFileName )
def visualizeMultiGFS( gfsFiles, cMap, outFileBases, imgFormat, mapRange=1.0, mapLimits=None, sites=None, obstacles=None ):
'''Visualizes multiple grid file sequence with the given color map (including a single, commmon range).
@param gfsFile A list of GridFileSequenceReader instances. The grids to visualize.
@param cMap An instance of ColorMap. Indicates how the visualization works.
@param outFileBases A list of strings. The basic names of the images to be output.
For each grid in the sequence, it outputs outFileBase_###.imgFormat.
The path must already exist. One path has to exist for gfsFile
@param imgFormat A string. The output image format (png, jpg, or bmp )
@param mapRange A float. Determines what fraction of the data range maps to the color
range. For example, if mapRange is 0.75, then the value that is
75% of the way between the min and max value achieves the maximum
color value. Ignored if mapLimits is not None.
@param mapLimits A tuple which defines the map range independent of the real values in
the data (minVal, maxVal). If the tuple has two values, that defines the range.
If either is None, then the corresponding value from the data is used.
@param sites An instance of pedestrian trajectory. It should have as many frames
of data as there are grids in the sequence.
@param obstacles An instance of ObstacleSet (optional). If obstacle are provided,
Then they will be drawn over the top of the data.
'''
pygame.init()
# make sure the path exists
for outFileBase in outFileBases:
path, name = os.path.split( outFileBase )
if ( not os.path.exists( path ) ):
os.makedirs( path )
digits = map( lambda x: int( np.ceil( np.log10( x.gridCount() ) ) ), gfsFiles )
minVal = min( map( lambda x: x.range[0], gfsFiles ) )
maxVal = max( map( lambda x: x.range[1], gfsFiles ) )
maxVal = ( maxVal - minVal ) * mapRange + minVal
if ( not mapLimits is None ):
if ( not isinstance( mapLimits, tuple ) ):
raise ValueError, "The parameter mapLimits must be a tuple"
elif ( len( mapLimits ) != 2 ):
raise ValueError, "The parameter mapLimits must have two values"
if ( not mapLimits[0] is None ):
minVal = mapLimits[0]
if ( not mapLimits[1] is None ):
maxVal = mapLimits[1]
for i, gfsFile in enumerate( gfsFiles ):
print gfsFile.summary()
outFileBase = outFileBases[ i ]
for grid, gridID in gfsFile:
try:
frame = None
if ( sites is not None ):
frame, frameID = sites.next()
fileName = '{0}{1:0{2}d}.{3}'.format( outFileBase, gridID, digits[i], imgFormat )
visualizeGrid( grid, cMap, fileName, minVal, maxVal, frame, obstacles )
except MemoryError:
print "Error on frame", gridID
raise
pygame.image.save( cMap.lastMapBar(7), '%s_bar.png' % ( outFileBase ) )
def visualizeGFS( gfsFile, cMap, outFileBase, imgFormat, mapRange=1.0, mapLimits=None, sites=None, obstacles=None ):
'''Visualizes a grid file sequence with the given color map.
@param gfsFile An instance of a GridFileSequenceReader. The grids to visualize.
@param cMap An instance of ColorMap. Indicates how the visualization works.
@param outFileBase A string. The basic name of the images to be output.
For each grid in the sequence, it outputs outFileBase_###.imgFormat.
The path must already exist.
@param imgFormat A string. The output image format (png, jpg, or bmp )
@param mapRange A float. Determines what fraction of the data range maps to the color
range. For example, if mapRange is 0.75, then the value that is
75% of the way between the min and max value achieves the maximum
color value. Ignored if mapLimits is not None.
@param mapLimits A tuple which defines the map range independent of the real values in
the data (minVal, maxVal). If the tuple has two values, that defines the range.
If either is None, then the corresponding value from the data is used.
@param sites An instance of pedestrian trajectory. It should have as many frames
of data as there are grids in the sequence.
@param obstacles An instance of ObstacleSet (optional). If obstacle are provided,
Then they will be drawn over the top of the data.
'''
pygame.init()
# make sure the path exists
path, name = os.path.split( outFileBase )
if ( not os.path.exists( path ) ):
os.makedirs( path )
print gfsFile.summary()
digits = int( np.ceil( np.log10( gfsFile.gridCount() ) ) )
if ( not mapLimits is None ):
if ( not isinstance( mapLimits, tuple ) ):
raise ValueError, "The parmeter mapLimits must be a tuple"
elif ( len( mapLimits ) != 2 ):
raise ValueError, "The parameter mapLimits must have two values"
minVal = gfsFile.range[0]
if ( not mapLimits[0] is None ):
minVal = mapLimits[0]
maxVal = gfsFile.range[1]
if ( not mapLimits[1] is None ):
maxVal = mapLimits[1]
else:
minVal = gfsFile.range[0]
maxVal = gfsFile.range[1]
maxVal = ( maxVal - minVal ) * mapRange + minVal
for grid, gridID in gfsFile:
try:
frame = None
if ( sites is not None ):
frame, frameID = sites.next()
fileName = '{0}{1:0{2}d}.{3}'.format( outFileBase, gridID, digits, imgFormat )
visualizeGrid( grid, cMap, fileName, minVal, maxVal, frame, obstacles )
except MemoryError:
print "Error on frame", gridID
raise
pygame.image.save( cMap.lastMapBar(7), '%sbar.png' % ( outFileBase ) )
def visualizeGFSName( gfsFileName, outFileBase, imgFormat='png', cMap=ColorMap.BlackBodyMap(), mapRange=1.0, mapLimits=None, sitesName=None, obstacles=None ):
'''Visualizes a grid file sequence with the given color map.
@param gfsFileName A string. The name of the GridFileSequence to visualize.
@param outFileBase A string. The basic name of the images to be output.
For each grid in the sequence, it outputs outFileBase_###.imgFormat.
The path must already exist.
@param imgFormat A string. The output image format (png, jpg, or bmp )
@param cMap An instance of ColorMap. Indicates how the visualization works.
@param mapRange A float. Determines what fraction of the data range maps to the color
range. For example, if mapRange is 0.75, then the value that is
75% of the way between the min and max value achieves the maximum
color value. Ignored if mapLimits is not None.
@param mapLimits A tuple which defines the map range independent of the real values in
the data (minVal, maxVal). If the tuple has two values, that defines the range.
If either is None, then the corresponding value from the data is used.
@param sitesName A string. The path to a set of trajectory sites
@param obstacles An instance of ObstacleSet (optional). If obstacle are provided,
Then they will be drawn over the top of the data.
'''
reader = GFS.GridFileSequenceReader( gfsFileName )
reader.setNext( 0 )
try:
sites = loadTrajectory( sitesName )
except:
sites = None
visualizeGFS( reader, cMap, outFileBase, imgFormat, mapRange, mapLimits, sites, obstacles )
if __name__ == '__main__':
def main():
import optparse
import ColorMap
import sys, os
import obstacles
from trajectory import loadTrajectory
parser = optparse.OptionParser()
parser.add_option( '-i', '--input', help='A path to a grid file sequence - the data to visualize',
action='store', dest='input', default='' )
parser.add_option( '-t', '--trajectory', help='(Optional) The path to the pedestrian data which produced the voronoi diagrams.',
action='store', dest='trajName', default=None )
parser.add_option( '-o', '--output', help='The path and base filename for the output images (Default is "vis").',
action='store', dest='output', default='./vis' )
parser.add_option( '-c', '--colorMap', help='Specify the color map to use. Valid values are: %s. Defaults to "black_body".' % ColorMap.getValidColorMaps(),
action='store', dest='cmapName', default='black_body' )
parser.add_option( '-e', '--extension', help='Image format: [png, jpg, bmp] (default is png)',
action='store', dest='ext', default='png' )
parser.add_option( '-b', '--obstacles', help='Path to an obstacle xml file',
action='store', dest='obstXML', default=None )
options, args = parser.parse_args()
if ( options.input == '' ):
print '\n *** You must specify an input file'
parser.print_help()
sys.exit(1)
try:
colorMap = ColorMap.getColorMapByName( options.cmapName )
except KeyError:
print '\n *** You have selected an invalid color map: %s' % ( options.cmapName )
parser.print_help()
sys.exit(1)
if ( not options.ext.lower() in ( 'png', 'jpg', 'bmp' ) ):
print '\n *** You have selected an invalid file format: %s' % ( options.ext )
parser.print_help()
sys.exit(1)
trajData = None
if ( not options.trajName is None ):
try:
trajData = loadTrajectory( options.trajName )
except ValueError:
print "Unable to recognize the data in the file: %s" % ( options.trajName )
folder, baseName = os.path.split( options.output )
if ( folder ):
if ( not os.path.exists( folder ) ):
os.makedirs( folder )
reader = GFS.GridFileSequenceReader( options.input )
reader.setNext( 0 )
obstacles = None
if ( options.obstXML ):
obstacles, bb = obstacles.readObstacles( options.obstXML )
visualizeGFS( reader, colorMap, options.output, options.ext, 1.0, trajData, obstacles )
main()