tvaLib
scene.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 # tvaLib Copyright (c) 2012-2016 Paul G. St-Aubin
3 # Ecole Polytechnique de Montreal, McGill University
4 # Python 2.7; (dt) Spyder Windows 10 64-bit; ipython Ubuntu 15.04 64-bit
5 
9 import os, csv
10 from datetime import timedelta, datetime
11 from copy import deepcopy
12 import math as m
13 
14 try: import numpy as np
15 except ImportError: raise Exception, [0101, 'Numpy is not installed.']
16 
17 import include.config as tvaConfig
18 import lib.tools as tvaLib
19 import lib.filt as tvaFilter
20 import lib.metadata as tvaMetaData
21 
22 
25 route_recursion_hard_limit = 7
26 
27 
30 class SQLlists(tvaLib.Constructors.SuperList, tvaLib.Constructors.SQLalchemyParser):
31  def __init__(self, class_prototype, sql_prototype, nonOptionalArgs, dir='', filename='scene.sqlite', **kwargs):
32  ''' Example usage:
33  SQLlists(Analysis, tvaMetaData.Analysis, config.dir, config.dbn, sites=sites, config=config)
34  '''
35  tvaLib.Constructors.SuperList.__init__(self)
36  self.nonOptionalArgs = nonOptionalArgs
37  self.prototype = sql_prototype
38  self.class_prototype = class_prototype
39  try: dir = kwargs['dir_overide']
40  except: pass
41  try: filename = kwargs['filename_overide']
42  except: pass
43  try: self.session = tvaMetaData.createDatabase(os.path.join(dir,filename))
44  except: raise Exception, [390, 'Scene database file "'+os.path.join(dir,filename)+'" does not exist.']
45  #sorted(self.session.query(self.prototype).all(), key=lambda mbr: operator.attrgetter('name')(mbr).lower())
46  for object_ in self.session.query(self.prototype).all():
47  self.data.append(self.class_prototype(object_, *nonOptionalArgs, **kwargs))
48  return
49 
50  def new(self, sqlFields={}, **classFields):
51  data = self.prototype(**sqlFields)
52  self.session.add_all([data])
53  self.session.commit()
54  self.data.append(self.class_prototype(data, *self.nonOptionalArgs, **classFields))
55  return True
56 
57  def update(self):
58  ''' Pass back any changes into SQLlist database. '''
59  objects = self.session.query(self.prototype).all()
60  for oIx in range(len(objects)):
61  objects[oIx] = self.data[oIx].write(objects[oIx])
62  self.session.add_all(objects)
63  self.session.commit()
64  return True
65 
66  def exportToCode(self, moduleName='tvaMetaData'):
67  for object_ in self:
68  object_.exportToCode(moduleName)
69  return True
70 
71  def objectFromDict(idx=0, **kwargs):
72  ''' Take a dict of object parameters and emulate equivalent sqlaclhemy
73  object with corresponding parameters. '''
74  from collections import namedtuple
75  struct = namedtuple('struct', ' '.join([kwarg for kwarg in kwargs]))
76  obj = struct(**kwargs)
77  obj.idx = idx
78  return obj
79 
80  def getAlchemyObject(self, idx):
81  ''' Use this to pull a raw SQLalchemy object (usefull for injecting
82  backreferences). Note the use of idx, and not Ix'''
83  return [x for x in self.session.query(self.prototype).all() if x.idx==idx][0]
84 
85 
88 class Sites(SQLlists):
89  def __init__(self, *nonOptionalArgs, **kwargs):
90  ''' nonOptionalArgs includes a configuration. '''
91  self.config = nonOptionalArgs[0]
92  SQLlists.__init__(self, Site, tvaMetaData.Site, nonOptionalArgs, dir=nonOptionalArgs[0].dir, filename=nonOptionalArgs[0].dbn, **kwargs)
93  return
94 
95  def getBaseDirectory(self): return self.config.dir
96 
97  def exportToCode(self, moduleName='tvaMetaData', recursive=True):
98  for site in self:
99  site.exportToCode(moduleName, recursive=recursive)
100  if(not recursive):
101  for site in self:
102  for camera in site:
103  camera.exportToCode(moduleName, recursive=False)
104  for site in self:
105  for camera in site:
106  for sequence in camera:
107  sequence.exportToCode(moduleName, recursive=False)
108  return
109 
110 
113 class Site(tvaLib.Constructors.SuperList, tvaLib.Constructors.SQLalchemyParser):
114  def __init__(self, site, config, **kwargs):
115  tvaLib.Constructors.SuperList.__init__(self)
116  self.config = config
117  self.idx = site.idx
118  self.name = site.name
119  self.description = site.description
120  self.xcoordinate = site.xcoordinate
121  self.ycoordinate = site.xcoordinate
122  self.satres = site.satres
123  self.satFilename = site.satFilename
124 
125  self.alignments = Alignments(site.alignments, sidewalks=site.sidewalks, bikepaths=site.bikepaths, corridorMinProximity=config.corridorMinProximity, corridorMinContinuousDistance=config.corridorMinContDistance, connectorSearchDistance=config.connectorSearchDistance, intersectionDistanceFactor=config.intersectionDistanceFactor)
126  #site.camera_views = sorted(site.camera_views, key=lambda mbr: operator.attrgetter('name')(mbr).lower())
127  for scene in site.camera_views: self.data.append(Scene(scene, self.config))
128 
129 
130  self.crossStreet1 = None
131  self.crossStreet2 = None
132  self.municipality = None
133  if(self.config.meta_db and os.path.exists(os.path.join(self.config.dir, self.config.meta_db))):
134  with open(os.path.join(self.config.dir, self.config.meta_db), 'rb') as f:
135  reader = csv.reader(f, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
136  labels = reader.next()
137  description_column = labels.index('description')
138  for row in reader:
139  if(row[description_column] == self.description):
140  try:
141  self.crossStreet1 = unicode(row[labels.index('street1')], 'utf8')
142  self.crossStreet2 = unicode(row[labels.index('street2')], 'utf8')
143  self.municipality = unicode(row[labels.index('municipality')], 'utf8')
144  except Exception:
145  self.crossStreet1 = unicode(row[labels.index('street1')], 'latin-1')
146  self.crossStreet2 = unicode(row[labels.index('street2')], 'latin-1')
147  self.municipality = unicode(row[labels.index('municipality')], 'latin-1')
148  return
149 
150  def new(self, sIdx, camTypeIdx, session, sqlFields={}):
151  sites = session.query(tvaMetaData.Site).all()
152  camType = session.query(tvaMetaData.CamType).all()
153  data = tvaMetaData.CameraView([x for x in sites if x.idx==sIdx][0], [x for x in camType if x.idx==camTypeIdx][0], **sqlFields)
154  session.add_all([data])
155  session.commit()
156  self.data.append(Scene(data, self.config))
157  return True
158 
159  def write(self, site):
160  site.idx = self.idx
161  site.name = self.name
162  site.description = self.description
163  site.xcoordinate = self.xcoordinate
164  site.ycoordinate = self.xcoordinate
165  site.satres = self.satres
166  site.satFilename = self.satFilename
167 
168  site.alignments = self.alignments.write()
169  site.sidewalks = self.alignments.sidewalks.write()
170  site.bikepaths = self.alignments.bikepaths.write()
171  for sceneIx in range(len(site.camera_views)):
172  site.camera_views[sceneIx] = self.data[sceneIx].write(site.camera_views[sceneIx])
173  return site
174 
175  def getBaseDirectory(self): return os.path.join(self.config.dir, self.name)
176  def getFullSatFilename(self): return os.path.join(self.config.dir, self.name, self.satFilename)
177 
178  def getCombinedMasks(self):
179  masks = tvaLib.Constructors.SuperList()
180  for camera in self:
181  masks + camera.mask
182  return masks
183 
184  def getADT(self, hourly_expansion_factors, **kwargs):
185  ''' Compute, update, and return Average Daily Traffic at this site. See
186  Scene.getADT() for more information.
187  '''
188  ADTs = filter(None, [scene.getADT(hourly_expansion_factors, **kwargs) for scene in self.data])
189  if(ADTs == []): return None
190  else: return float(sum(ADTs))/float(len(ADTs))
191 
192  def getAADT(self, hourly_expansion_factors, doweek_expansion_factors, monthly_expansion_factors, **kwargs):
193  ''' Compute, update, and return Average Annual Daily Traffic at this
194  site. See Scene.getADT() for more information
195  '''
196  AADTs = filter(None, [scene.getAADT(hourly_expansion_factors, doweek_expansion_factors, monthly_expansion_factors, **kwargs) for scene in self.data])
197  if(AADTs == []): return None
198  else: return float(sum(AADTs))/float(len(AADTs))
199 
200  def exportToCode(self, moduleName='tvaMetaData', justifyCol1=35, justifyCol2=10, recursive=True):
201  print("sites.append("+moduleName+".Site("+("'"+self.name+"',").ljust(justifyCol1)+(" '"+self.description+"',").ljust(justifyCol2)+" satres="+str(self.satres)+", satFilename='"+self.satFilename+"', alignments='"+self.alignments.write()+"'))")
202  if(recursive):
203  for camera in self: camera.exportToCode(moduleName, recursive=recursive)
204 
205 
208 class Scene(tvaLib.Constructors.SuperList, tvaLib.Constructors.SQLalchemyParser):
209  def __init__(self, scene, config):
210  tvaLib.Constructors.SuperList.__init__(self)
211  self.config = config
212  self.idx = scene.idx
213  self.site = scene.site
214  self.name = scene.name
215  self.homographyFilename = scene.homographyFilename
216  self.homographyDistanceUnit = scene.homographyDistanceUnit
217  self.cameraCalibrationFilename = scene.cameraCalibrationFilename
218  self.configurationFilename = scene.configurationFilename
219  self.defaultFullCfgFilename = 'tracking.cfg'
220  self.maskFilename = scene.maskFilename
221  self.camHeight = scene.camHeight
222 
223  self.homography = tvaLib.Constructors.SuperListParse(scene.homography, dimension=2, datatype='float')
224  self.mask = tvaLib.Constructors.SuperListParse(scene.mask, dimension=3, datatype='point')
225  self.camOrigin = tvaLib.Constructors.SuperListParse(scene.camOrigin, dimension=1, datatype='float')
226  self.camera = CameraType(scene.camera, self.config)
227  for sequence in scene.video_sequences:
228  self.data.append(Sequence(sequence, self.config))
229 
230  self.defaultFullCfgFilename = os.path.join(self.config.path_to_trafint, 'tracking.cfg')
231  return
232 
233  def new(self, camIdx, session, sqlFields={}):
234  cameras = session.query(tvaMetaData.CameraView).all()
235  data = tvaMetaData.VideoSequence([x for x in cameras if x.idx==camIdx][0], **sqlFields)
236  session.add_all([data])
237  session.commit()
238  self.data.append(Sequence(data, self.config))
239  return True
240 
241  def write(self, scene):
242  scene.idx = self.idx
243  scene.name = self.name
244  scene.homographyFilename = self.homographyFilename
245  scene.homographyDistanceUnit = self.homographyDistanceUnit
246  scene.cameraCalibrationFilename = self.cameraCalibrationFilename
247  scene.configurationFilename = self.configurationFilename
248  scene.maskFilename = self.maskFilename
249  scene.camHeight = self.camHeight
250 
251  scene.homography = self.homography.write()
252  scene.mask = self.mask.write()
253  scene.camOrigin = self.camOrigin.write()
254  for fileIx in range(len(scene.video_sequences)):
255  scene.video_sequences[fileIx] = self.data[fileIx].write(scene.video_sequences[fileIx])
256  return scene
257 
258  def getHomography(self, type='undistorted'):
259  ''' Start with the premise that the existing homographies are in
260  undistorted space (legacy). TODO: Invert this with a config option.
261  '''
262 
263  if(self.homography): h = self.homography
264  elif(self.homographyFilename):
265  if(self.getFullHomographyFilename()):
266  self.setHomography(np.loadtxt(self.getFullHomographyFilename()))
267  h = self.homography
268  else: return None
269  else: return None
270 
271 
272  if(type=='undistorted'): return h
273 
274  elif(type=='distorted'):
275  new_h = np.dot(np.array(h.data), np.linalg.inv(np.array(self.camera.getCamMatrix().data)))
276  return new_h/new_h[2][2]
277  else: return None
278 
279  def setHomography(self, value):
280  if(type(value) is np.ndarray): self.homography = tvaLib.Constructors.SuperListParse(value.tolist(), dimension=2, datatype='float')
281  elif(type(value) is list): self.homography = tvaLib.Constructors.SuperListParse(value, dimension=2, datatype='float')
282  else: self.homography = value
283 
284  def getBaseDirectory(self): return os.path.join(self.config.dir, self.site.name, self.name)
285  def getClassificationTrainingBaseDirectory(self, type): return os.path.join(self.config.dir, 'Calibration', 'Data', type, self.site.name+'_'+self.name)
286  def getFullHomographyFilename(self, force=False):
287  if(os.path.exists(os.path.join(self.config.dir, self.site.name, self.name, self.homographyFilename)) or force): return os.path.join(self.config.dir, self.site.name, self.name, self.homographyFilename)
288  elif(self.homography):
289  with open(os.path.join(self.config.temp_dir, tvaLib.Parse.clean_file_name('homography-'+str(self.config.dbn)[:-7]+'-'+str(self.idx)+'-'+str(self.name)+'.txt')), 'wb') as f:
290  for line in self.homography:
291  f.write(' '.join([str(x) for x in line])+'\n')
292  return os.path.join(self.config.temp_dir, tvaLib.Parse.clean_file_name('homography-'+str(self.config.dbn)[:-7]+'-'+str(self.idx)+'-'+str(self.name)+'.txt'))
293  return ''
294  def getFullCameraCalibrationFilename(self): return os.path.join(self.config.dir, self.site.name, self.name, self.cameraCalibrationFilename)
296  if(self.configurationFilename and os.path.exists(os.path.join(self.config.dir, self.site.name, self.name, self.configurationFilename))): return os.path.join(self.config.dir, self.site.name, self.name, self.configurationFilename)
297  elif(self.configurationFilename and os.path.exists(os.path.join(self.config.dir, self.configurationFilename))): return os.path.join(self.config.dir, self.configurationFilename)
298  else: return self.defaultFullCfgFilename
299  def getFullMaskFilename(self): return os.path.join(self.config.dir, self.site.name, self.name, self.maskFilename)
300  def getStartTime(self):
301  if(not self.data): return None
302  return min([x.getStartTime() for x in self.data])
303  def getEndTime(self):
304  if(not self.data): return None
305  return max([x.getEndTime() for x in self.data])
306 
307 
308  def getADT(self, hourly_expansion_factors, exposure='traffic', customCount=None, customHour=None, **kwargs):
309  ''' Calculate and update Average Daily Traffic.
310 
311  Input:
312  ======
313  exposure: type of data to use (see below)
314  customCount: custom count to use (leave blank if estimating from tracking)
315  customHour: custom hour to use with customCount
316 
317  Exposure options include:
318  =========================
319  exposure=='traffic' or 't': Average Daily Traffic (ADT) [Default]
320  exposure=='pair' or 'pe': Average Daily user Pair Exposure (ADPE)
321  exposure=='instance' or 'interaction' or 'ie': Average Daily interaction Instant Exposure (ADIE)
322  exposure=='pairind' or 'pi': Average Daily user Pair Indicator Exposure (ADPIE)
323  exposure=='instanceind' or 'ii': Average Daily interaction Instant Indicator Exposure (ADIIE)
324  exposure==int between 0 and 6: Average Daily [corresponding user type] (AD[UT])
325 
326 
327  Notes:
328  ======
329  * All expansion factors are simple lists of normalised fractional
330  proportions, the sum of which should equal 1.0.
331  * Optionally, you can pass a custom exposure input and sequence time
332  which will be used instead of exposure
333  '''
334 
335  if(customCount and customHour):
336  for sequence in self.data:
337  if(sequence.getHour() == customHour): return customCount*3600.0/float(hourly_expansion_factors[sequence.getHour()]*sequence.duration)
338  return None
339 
340 
341 
342 
343  if(type(exposure) is str): exposure=exposure.lower()
344  if(exposure=='pair' or exposure=='pe'): exposure_type = 1 #(ADPE)
345  elif(exposure=='instance' or exposure=='interaction' or exposure=='ie'): exposure_type = 2 #(ADIE)
346  elif(exposure=='pairind' or exposure=='pi'): exposure_type = 3 #(ADPIE)
347  elif(exposure=='instanceind' or exposure=='ii'): exposure_type = 4 #(ADIIE)
348  elif(type(exposure) is int and exposure>=0 and exposure<=6): exposure_type = 5 #(AD[UT])
349  else: exposure_type = 0 #(ADT)
350 
351 
352  ADTs = []
353  for sequence in self.data:
354  if(sequence.duration > 0):
355  if(exposure_type==1 and sequence.countExpPairs > 0): ADTs.append(sequence.countExpPairs *3600.0/float(hourly_expansion_factors[sequence.getHour()]*sequence.duration))
356  elif(exposure_type==2 and sequence.countExpInstances > 0): ADTs.append(sequence.countExpInstances *3600.0/float(hourly_expansion_factors[sequence.getHour()]*sequence.duration))
357  elif(exposure_type==3 and sequence.countExpPairsWInd > 0): ADTs.append(sequence.countExpPairsWInd *3600.0/float(hourly_expansion_factors[sequence.getHour()]*sequence.duration))
358  elif(exposure_type==4 and sequence.countExpInstancesWInd > 0): ADTs.append(sequence.countExpInstancesWInd*3600.0/float(hourly_expansion_factors[sequence.getHour()]*sequence.duration))
359  elif(exposure_type==5 and sequence.countByType[exposure] > 0): ADTs.append(sequence.countByType[exposure]*3600.0/float(hourly_expansion_factors[sequence.getHour()]*sequence.duration))
360  elif(exposure_type==0 and sequence.countObjects > 0): ADTs.append(sequence.countObjects *3600.0/float(hourly_expansion_factors[sequence.getHour()]*sequence.duration))
361 
362 
363  if(not ADTs): return None
364  else: return sum(ADTs)/float(len(ADTs))
365 
366 
367  def getAADT(self, hourly_expansion_factors, doweek_expansion_factors, monthly_expansion_factors, **kwargs):
368  ''' Compute, update, and return Average Daily Traffic. See
369  Scene.getADT() for list of exposure types.
370 
371  Notes:
372  ======
373  * All expansion factors are simple lists of normalised fractional
374  proportions, the sum of which should equal 1.0.
375  * The first item in doweek_expansion_factors is Monday.
376  '''
377  ADT = self.getADT(hourly_expansion_factors, **kwargs)
378  if(ADT is None): return None
379  doweek_index = self.data[0].getWeekday()-1
380  monthly_index = self.data[0].getMonth()-1
381  return ADT*doweek_expansion_factors[doweek_index]*7.0*monthly_expansion_factors[monthly_index]*12.0
382 
383  def getCountObjects(self):
384  if(len(self.data) > 0 and hasattr(self.data[0], 'countObjects')): return sum([x.countObjects for x in self.data])
385  else: return 0
386  def getCountObjOld(self):
387  if(len(self.data) > 0 and hasattr(self.data[0], 'countObjOld')): return sum([x.countObjOld for x in self.data])
388  else: return 0
389  def getDuration(self):
390  if(len(self.data) > 0 and hasattr(self.data[0], 'duration')): return sum([x.duration for x in self.data])
391  else: return 0
392  def getDurationUnit(self):
393  if(len(self.data) > 0 and hasattr(self.data[0], 'durationUnit')): return self.data[0].durationUnit
394  else: return 's'
395 
396 
397  def exportToCode(self, moduleName='tvaMetaData', justifyCol1=20, justifyCol2=35, recursive=True):
398  print("cameras.append("+moduleName+".CameraView(([x for x in sites if x.name=='"+(self.site.name+"'][0],").ljust(justifyCol1)+" [x for x in camTypes if x.name=='"+(self.camera.name+"'][0],").ljust(justifyCol2)+" '"+self.name+"', homographyFilename='"+self.homographyFilename+"'))")
399  if(recursive):
400  for sequence in self: sequence.exportToCode(moduleName, recursive=recursive)
401 
402 
405 class Sequence(tvaLib.Constructors.SQLalchemyParser):
406  def __init__(self, sequence, config):
407 
408  self.config = config
409  self.idx = sequence.idx
410  self.cameraView = sequence.cameraView
411  self.videoFilename = sequence.videoFilename
412  self.dataFilename = sequence.dataFilename
413  self.name = os.path.splitext(self.dataFilename)[0]
414  self.startTime = sequence.startTime
415  self.duration = sequence.duration
416  self.durationUnit = sequence.durationUnit
417  self.translationX = sequence.translationX
418  self.translationY = sequence.translationY
419  self.rotation = sequence.rotation
420  self.legacy = False
421 
422  if(os.path.splitext(self.dataFilename)[-1] == '.sqlite'): self.legacy = False
423  else: self.legacy = True
424  self.countObjects = 0
425  self.countObjOld = 0
426  self.countExpPairs = 0
430  self.countByType = dict((x,0) for x in range(7))
431  return
432 
433 
434  def getBaseDirectory(self): return os.path.join(self.config.dir, self.cameraView.site.name, self.cameraView.name)
435  def getFullDataFilename(self): return os.path.join(self.config.dir, self.cameraView.site.name, self.cameraView.name, self.dataFilename)
436  def getFullSerialisedFilename(self): return os.path.join(self.config.dir, self.cameraView.site.name, self.cameraView.name, self.name+'.traj')
437  def getFullClassifiedFilename(self): return os.path.join(self.config.dir, self.cameraView.site.name, self.cameraView.name, self.name+'-cl.sqlite')
438  def getFullGroundTruthFilename(self): return os.path.join(self.config.dir, self.cameraView.site.name, self.cameraView.name, self.name+'-gt.sqlite')
439  def getFullAnnotationFilename(self): return os.path.join(self.config.dir, self.cameraView.site.name, self.cameraView.name, self.name+'.annotation')
440  def getFullEventsFilename(self): return os.path.join(self.config.dir, self.cameraView.site.name, self.cameraView.name, self.name+'.events')
441  def getFullEventsCSVFilename(self): return os.path.join(self.config.dir, self.cameraView.site.name, self.cameraView.name, self.name+'-events.csv')
442  def getFullVideoFilename(self, forceDistorted=False, allowNonExistant=False):
443  if(self.cameraView.camera.camera_matrix and forceDistorted): name = self.name+'-undistort.avi'
444  else: name = self.videoFilename
445  if(allowNonExistant): return os.path.join(self.config.dir, self.cameraView.site.name, self.cameraView.name, name)
446  elif(os.path.exists(os.path.join(self.config.dir, self.cameraView.site.name, self.cameraView.name, name))): return os.path.join(self.config.dir, self.cameraView.site.name, self.cameraView.name, name)
447  else: return ''
448  def getImageSpaceFrameFilename(self, forceDistorted=False, allowNonExistant=False):
449  if(self.cameraView.camera.camera_matrix and forceDistorted): undistort = '-undistort'
450  else: undistort = ''
451  if(os.path.exists(os.path.join(self.config.dir, self.cameraView.site.name, self.cameraView.name, self.name+undistort+'.png'))): return os.path.join(self.config.dir, self.cameraView.site.name, self.cameraView.name, self.name+undistort+'.png')
452  elif(allowNonExistant): return os.path.join(self.config.dir, self.cameraView.site.name, self.cameraView.name, self.name+'-frame'+undistort+'.png')
453  elif(os.path.exists(os.path.join(self.config.dir, self.cameraView.site.name, self.cameraView.name, self.name+'-frame'+undistort+'.png'))): return os.path.join(self.config.dir, self.cameraView.site.name, self.cameraView.name, self.name+'-frame'+undistort+'.png')
454  else: return tvaLib.crawlDirsForFilePattern(pattern='*frame'+undistort+'.png', path=os.path.join(self.config.dir, self.cameraView.site.name, self.cameraView.name), returnList=False)
455 
456  def write(self, sequence):
457  sequence.idx = self.idx
458  sequence.videoFilename = self.videoFilename
459  sequence.dataFilename = self.dataFilename
460  sequence.startTime = self.startTime
461  sequence.duration = self.duration
462  sequence.durationUnit = self.durationUnit
463  sequence.translationX = self.translationX
464  sequence.translationY = self.translationY
465  sequence.rotation = self.rotation
466  return sequence
467 
468  def getYear(self): return self.startTime.year
469  def getMonth(self): return self.startTime.month
470  def getDay(self): return self.startTime.day
471  def getHour(self): return self.startTime.hour
472  def getMinute(self): return self.startTime.minute
473  def getSecond(self): return self.startTime.second
474  def getWeekday(self): return self.startTime.weekday()+1 # From 1 to 7 where Monday=1 and Sunday = 7
475  def getStartTime(self): return self.startTime
476  def getEndTime(self): return self.startTime+timedelta(0,self.duration)
477  def getDuration(self): return self.duration
478 
479  def isParallelSequenceTo(self, sequence, maxDiffSec=60):
480  timedelta = self.startTime - sequence.startTime
481  if(timedelta.seconds > maxDiffSec or timedelta.seconds < -maxDiffSec): return False
482  else: return True
483 
484 
485  def setCountsFromObjects(self, objects):
486  self.setCountObjects(len(objects))
487  for userType in self.countByType: self.setCountUserType(len([1 for obj in objects if obj.userType==userType]), userType)
488  def setCountObjects(self, value): self.countObjects = value
489  def setCountUserType(self, value, i): self.countByType[i] = value
490  def setCountObjOld(self, value): self.countObjOld = value
491  def setCountExpPairs(self, value): self.countExpPairs = value
492  def setCountExpInstances(self, value): self.countExpInstances = value
493  def setCountExpPairsWInd(self, value): self.countExpPairsWInd = value
494  def setCountExpInstancesWInd(self, value): self.countExpInstancesWInd = value
495  def setDuration(self, value): self.duration = value
496  def setRotation(self, value): self.rotation = value
497  def setTranslation(self, x, y):
498  self.translationX = x
499  self.translationY = y
500 
501 
502  def exportToCode(self, moduleName='tvaMetaData'):
503  print("sequences.append("+moduleName+".VideoSequence([x for x in cameras if x.name=='"+self.cameraView.name+"' and x.site.name=='"+self.cameraView.site.name+"'][0], '"+self.videoFilename+"', '"+str(self.startTime)+"', "+str(self.duration)+"))")
504 
505  def loadObjects(self, filename_override='', max_obj=None, max_obj_features=999, suppress_features=False, load_gt=False, indent=0, verbose=0):
506  ''' Manage trajectory loading according to sequence settings and commands. '''
507 
508  if(self.legacy): from ubc_utils import loadTrajectories
509  else:
510  from sys import stdout;oldstdout = stdout;stdout = tvaConfig.NullWriter()
511  try: import storage as TrafIntStorage
512  finally: stdout = oldstdout
513 
514 
515  if(filename_override): path_to_file = os.path.join(self.getBaseDirectory(), filename_override)
516  else: path_to_file = self.getFullDataFilename()
517  if(not os.path.exists(path_to_file)): raise Exception, [383, 'Unable to locate trajectory file on disk "'+path_to_file+'".']
518 
519 
520  objects = None
521  if(max_obj==-1): max_obj = None
522  if(not load_gt):
523  if(self.legacy): objects = loadTrajectories(path_to_file, max_obj)
524  else: objects = TrafIntStorage.loadTrajectoriesFromSqlite(path_to_file, 'object', max_obj)
525 
526  if(not objects or load_gt): return self.loadAnnotations(indent=indent, verbose=verbose)
527 
528 
529  if(not suppress_features):
530  if(self.legacy): features = loadTrajectories(os.path.join(self.getBaseDirectory(), self.name+'-features.txt'))
531  else: features = TrafIntStorage.loadTrajectoriesFromSqlite(path_to_file, 'feature')
532  for j in range(len(objects)):
533  #try:
534  objects[j].featureNumbers = tvaLib.Math.sample(objects[j].featureNumbers, sampleSize=max_obj_features, method='interpolation')
535  objects[j].setFeatures(features)
536  #except:
537  # from tools import printWarning as tvaLib_printWarning
538  # tvaLib_printWarning('There was a problem with the integrity of the feature database at object '+str(j)+' out of '+str(len(objects))+': some features are missing. This object will be dropped and analysis will continue...', 'Warning')
539  # objects[j] = None
540  objects = filter(None, objects)
541 
542 
543  if(verbose): print(''.rjust(indent,' ')+'Finished loading {0} objects.'.format(len(objects)))
544  return objects
545 
546  def loadAnnotations(self, forceNonGTFilename=False, indent=0, legacy=False, verbose=0):
547  ''' Manage annotation loading according to sequence settings and commands. '''
548 
549  from sys import stdout;oldstdout = stdout;stdout = tvaConfig.NullWriter()
550  try: import storage as TrafIntStorage
551  finally: stdout = oldstdout
552 
553 
554  if(legacy):
555  if(forceNonGTFilename): objects = TrafIntStorage.loadGroundTruthFromSqlite(self.getFullDataFilename())
556  else: objects = TrafIntStorage.loadGroundTruthFromSqlite(self.getFullGroundTruthFilename())
557  homography = np.loadtxt(os.path.join(self.config.dir, self.cameraView.site.name, self.cameraView.name, self.cameraView.homographyFilename))
558  for obj in objects:
559  obj.computeCentroidTrajectory(homography)
560 
562  else:
563  if(forceNonGTFilename): objects = TrafIntStorage.loadTrajectoriesFromSqlite(self.getFullDataFilename(), 'object')
564  else: objects = TrafIntStorage.loadTrajectoriesFromSqlite(self.getFullGroundTruthFilename(), 'object')
565 
566 
567  if(verbose): print(''.rjust(indent,' ')+'Finished loading {0} annotations.'.format(len(objects)))
568  return objects
569 
570 
574  def __init__(self, *nonOptionalArgs, **kwargs):
575  SQLlists.__init__(self, Cluster, tvaMetaData.Cluster, nonOptionalArgs, dir=nonOptionalArgs[0].dir, filename=nonOptionalArgs[0].dbn, **kwargs)
576  return
577 
578  def getNamedClusterByidx(self, idx): return [x for x in self if x.idx==idx][0]
579  def getNamedClusterByName(self, name): return self.getNamedClusters()[name]
580 
581  def getNamedClusters(self):
582  namedClusters = dict([(x.name, x) for x in self])
583  for x in self: namedClusters[x.name].append(x)
584  return namedClusters
585 
586 
587 class Cluster(tvaLib.Constructors.SuperList, tvaLib.Constructors.SQLalchemyParser):
588  def __init__(self, cluster, config):
589  ''' Each entry is a single cluster out of a group defined by a common
590  cluster.name . Point to specific site_analyses and/or to analyses
591  as a whole.
592 
593  xref_dbname can also be used to cross-reference a different
594  database name. This database has to be placed in the same folder as
595  the parent cluster folder.
596 
597  The order of clusters determines the cluster number.
598  '''
599  tvaLib.Constructors.SuperList.__init__(self)
600  self.idx = cluster.idx
601  self.name = cluster.name
602  self.xref_dbname = tvaLib.Constructors.SuperListParse(cluster.xref_dbname, type='str', dimension=1, removeEmpty=False)
603  self.analyses = tvaLib.Constructors.SuperListParse(cluster.analyses, type='int', dimension=1)
604  self.site_analyses = tvaLib.Constructors.SuperListParse(cluster.site_analyses, type='int', dimension=1)
605  self.labels = tvaLib.Constructors.SuperListParse(cluster.labels, type='str', dimension=1, removeEmpty=False)
606  self.colours = tvaLib.Constructors.SuperListParse(cluster.colours, type='str', dimension=1, removeEmpty=False)
607  self.plot_sites = cluster.plot_sites
608  self.size = max(len(self.xref_dbname), len(self.analyses), len(self.site_analyses), len(self.labels), len(self.colours))
609  if(not self.site_analyses): self.site_analyses = [None for x in range(self.size)]
610  if(not self.labels): self.labels = ['' for x in range(self.size)]
611  return
612  def __getitem__(self, i): return self.analyses[i]
613  def __len__(self): return self.size
614  def __iter__(self): return iter(zip(self.xref_dbname, self.analyses, self.site_analyses, self.labels, self.colours))
615 
616 
617 
619  def __init__(self, *nonOptionalArgs, **kwargs):
620  SQLlists.__init__(self, Analysis, tvaMetaData.Analysis, nonOptionalArgs, dir=nonOptionalArgs[0].dir, filename=nonOptionalArgs[0].dbn, **kwargs)
621  return
622 
623 class Analysis(tvaLib.Constructors.SuperList, tvaLib.Constructors.SQLalchemyParser):
624  def __init__(self, analysis, config):
625  tvaLib.Constructors.SuperList.__init__(self)
626  self.idx = analysis.idx
627  self.name = analysis.name
628  self.site_analyses = tvaLib.Constructors.SuperListParse(analysis.site_analyses, type='int', dimension=1)
629  return
630 
631 
633  def __init__(self, *nonOptionalArgs, **kwargs):
634  SQLlists.__init__(self, SiteAnalysis, tvaMetaData.SiteAnalysis, nonOptionalArgs, dir=nonOptionalArgs[0].dir, filename=nonOptionalArgs[0].dbn, **kwargs)
635  return
636 
637 class SiteAnalysis(tvaLib.Constructors.SuperList, tvaLib.Constructors.SQLalchemyParser):
638  def __init__(self, site_analysis, config, sites=None):
639  tvaLib.Constructors.SuperList.__init__(self)
640  self.config = config
641  self.idx = site_analysis.idx
642  self.name = site_analysis.name
643  self.startTimes = site_analysis.startTimes
644  self.endTimes = site_analysis.endTimes
645  self.description = site_analysis.description
646  self.configurationFilename = site_analysis.configurationFilename
647  self.temp_avg = site_analysis.temp_avg
648  self.precipitation = site_analysis.precipitation
649  self.glare = site_analysis.glare
650  self.geo_1 = site_analysis.geo_1
651  self.geo_2 = site_analysis.geo_2
652  self.geo_3 = site_analysis.geo_3
653  self.geo_4 = site_analysis.geo_4
654  self.geo_5 = site_analysis.geo_5
655  self.max_speed = site_analysis.max_speed
656  self.hex_grid_x = site_analysis.hex_grid_x
657  self.hex_grid_y = site_analysis.hex_grid_y
658 
659 
661  self.camIds = tvaLib.Constructors.SuperListParse(site_analysis.camIds, dimension=1)
662  self.cameras = [item for sublist in [[cam for cam in site if cam.idx in self.camIds] for site in sites] for item in sublist]
663  self.zone = tvaLib.Constructors.SuperListParse(site_analysis.zone, dimension=3, datatype='point')
664  if(self.cameras):
665  self.site = Site(self.cameras[0].site, self.config)
666  self.virtual_loops = VirtualLoops(site_analysis.virtual_loops, nLanes=len(self.site.alignments))
667  else: self.virtual_loops = VirtualLoops(site_analysis.virtual_loops, nLanes=0)
668  self.xy_bounds = tvaLib.Constructors.SuperListParse(site_analysis.xy_bounds, datatype='bound')
669  self.cm_bounds = tvaLib.Constructors.SuperListParse(site_analysis.cm_bounds, datatype='bound')
670  #Time Intervals
671  self.timeIntervals = []
672  if(self.startTimes != 'all' and self.endTimes != 'all'):
673  startTimes = tvaLib.Constructors.SuperListParse(self.startTimes, dimension=1)
674  endTimes = tvaLib.Constructors.SuperListParse(self.startTimes, dimension=1)
675  for intervalIx in range(min(len(startTimes),len(endTimes))):
676  self.timeIntervals.append([datetime.strptime(startTimes[intervalIx], '%Y-%m-%d %H:%M:%S'),datetime.strptime(endTimes[intervalIx], '%Y-%m-%d %H:%M:%S')])
677  #Expansion factors
678  try: self.monthly_expansion_factors_data = site_analysis.monthly_expansion_factors
679  except: self.monthly_expansion_factors_data = None
680  try: self.doweek_expansion_factors_data = site_analysis.doweek_expansion_factors
681  except: self.doweek_expansion_factors_data = None
682  try: self.hourly_expansion_factors_data = site_analysis.expansion_factors
683  except: self.hourly_expansion_factors_data = None
685  self.monthly_expansion_factors = tvaLib.Constructors.SuperListParse(self.monthly_expansion_factors_data, dimension=1)
686  if(len(self.monthly_expansion_factors) != 12): self.monthly_expansion_factors = None
687  else: self.monthly_expansion_factors = config.monthly_expansion_factors
689  self.doweek_expansion_factors = tvaLib.Constructors.SuperListParse(self.doweek_expansion_factors_data, dimension=1)
690  if(len(self.doweek_expansion_factors) != 7): self.doweek_expansion_factors = None
691  else: self.doweek_expansion_factors = config.doweek_expansion_factors
693  self.hourly_expansion_factors = tvaLib.Constructors.SuperListParse(self.hourly_expansion_factors_data, dimension=1)
694  if(len(self.hourly_expansion_factors) != 24): self.hourly_expansion_factors = None
695  else: self.hourly_expansion_factors = config.hourly_expansion_factors
696 
697  if(not self.name): self.name = tvaLib.flatten_list([[site.name for y in site if y.idx in self.camIds] for site in sites])[0]+':'+','.join([x.name for x in self.cameras])
698  self.resultsFolder = str(self.idx)+'_'+''.join([c for c in self.name if c.isalpha() or c.isdigit() or c==' ']).rstrip()[:35]
699  return
700 
701  def write(self, site_analysis):
702  site_analysis.idx = self.idx
703  site_analysis.name = self.name
704  site_analysis.startTimes = self.startTimes
705  site_analysis.endTimes = self.endTimes
706  site_analysis.description = self.description
707  site_analysis.configurationFilename = self.configurationFilename
708  site_analysis.temp_avg = self.temp_avg
709  site_analysis.precipitation = self.precipitation
710  site_analysis.glare = self.glare
711  site_analysis.geo_1 = self.geo_1
712  site_analysis.geo_2 = self.geo_2
713  site_analysis.geo_3 = self.geo_3
714  site_analysis.geo_4 = self.geo_4
715  site_analysis.geo_5 = self.geo_5
716  site_analysis.max_speed = self.max_speed
717  site_analysis.hex_grid_x = self.hex_grid_x
718  site_analysis.hex_grid_y = self.hex_grid_y
719 
720  site_analysis.zone = self.zone.write()
721  site_analysis.virtual_loops = self.virtual_loops.write()
722  site_analysis.xy_bounds = self.xy_bounds.write()
723  site_analysis.cm_bounds = self.cm_bounds.write()
724 
725  try: site_analysis.monthly_expansion_factors = self.monthly_expansion_factors.write()
726  except: pass
727  try: site_analysis.doweek_expansion_factors = self.doweek_expansion_factors.write()
728  except: pass
729  try: site_analysis.expansion_factors = self.hourly_expansion_factors.write()
730  except: pass
731  return site_analysis
732 
733  def getFullResultsFolder(self, analysis=None, customSubPath=''):
734  if(analysis==None): analysis = self.config.output_folder
735  if(not os.path.exists(os.path.join(self.config.dir, analysis, self.resultsFolder, customSubPath))): os.makedirs(os.path.join(self.config.dir, analysis, self.resultsFolder, customSubPath))
736  return os.path.join(self.config.dir, analysis, self.resultsFolder, customSubPath)
737  def getFullConfigurationFilename(self, analysis='Analysis'):
738  if(self.configurationFilename and os.path.exists(os.path.join(self.getFullResultsFolder(analysis), self.configurationFilename))): return os.path.join(self.getFullResultsFolder(self.config.dir, analysis), self.configurationFilename)
739  else: return self.cameras[0].getFullConfigurationFilename()
740 
741  def getGridHexSize(self):
742  if(not self.hex_grid_x or not self.hex_grid_y): return self.config.hex_grid_dimension
743  else: return [self.hex_grid_x, self.hex_grid_y]
744  def getCombinedMasks(self): return self.site.getCombinedMasks()
745  def getCamSeqs(self): return self.getCamSeqsInInterval(None)
746  def getCountObjects(self): return sum([cam.getCountObjects() for cam in self.cameras])
747  def getDurationUnit(self): return self.cameras[0].getDurationUnit()
748  def getDuration(self): return sum([cam.getDuration() for cam in self.cameras])
749  def getStartTime(self): return min([cam.getStartTime() for cam in self.cameras])
750  def getEndTime(self): return max([cam.getEndTime() for cam in self.cameras])
751  def getSequenceCount(self): return sum([len(cam) for cam in self.cameras])
752 
753  def getCamSeqs_Hourly(self):
754  ''' Return dictionary of daily hours (0-23) containing a list of
755  sequences associated with that hour. '''
756  hours = {}
757  for camera in self.cameras:
758  for sequence in camera:
759  if(sequence.getHour() not in hours): hours[sequence.getHour()] = [sequence]
760  else: hours[sequence.getHour()].append(sequence)
761  return hours
762 
763  def getCamSeqs_AMPM(self):
764  ''' Return a dictionary of AM and PM values containing a list of
765  sequences associated with that time (AM->0-11, PM->12-23). '''
766  ampm = {'am':[],'pm':[]}
767  for camera in self.cameras:
768  for sequence in camera:
769  if(sequence.getHour() <= 11): ampm['am'].append(sequence)
770  else: ampm['pm'].append(sequence)
771  return ampm
772 
773  def getCamSeqsInInterval(self, i):
774  ''' If i is None (default), or no timeIntervals defined, returns all
775  sequences on all intervals. '''
776  cam_seqs = []
777  for camera in self.cameras:
778  for sequence in camera:
779  if(i == None or not self.timeIntervals):
780  cam_seqs.append(sequence)
781  # TODO: filter by timeinterval (as opposed to just dumping all)
782  #import pdb; pdb.set_trace()
783  return cam_seqs
784 
785  def getADT(self, hourly_expansion_factors=None, **kwargs):
786  ''' Compute, update, and return Average Daily Traffic. See
787  Scene.getADT() for more information.
788  '''
789  if(not hourly_expansion_factors and not self.hourly_expansion_factors): return False
790  if(self.hourly_expansion_factors): hourly_expansion_factors = self.hourly_expansion_factors
791  ADTs = filter(None, [cam.getAADT(hourly_expansion_factors, **kwargs) for cam in self.cameras])
792  if(ADTs == []): return None
793  else: return sum(ADTs)/float(len(ADTs))
794 
795  def getAADT(self, hourly_expansion_factors=None, doweek_expansion_factors=None, monthly_expansion_factors=None, **kwargs):
796  ''' Compute, update, and return Average Annual Daily Traffic. See
797  Scene.getADT() for list of exposure types.
798  '''
799  if((not monthly_expansion_factors and not self.monthly_expansion_factors) or (not doweek_expansion_factors and not self.doweek_expansion_factors) or (not hourly_expansion_factors and not self.hourly_expansion_factors)): return False
800  if(self.monthly_expansion_factors): monthly_expansion_factors = self.monthly_expansion_factors
801  if(self.doweek_expansion_factors): doweek_expansion_factors = self.doweek_expansion_factors
802  if(self.hourly_expansion_factors): hourly_expansion_factors = self.hourly_expansion_factors
803  AADTs = filter(None, [cam.getAADT(hourly_expansion_factors, doweek_expansion_factors, monthly_expansion_factors, **kwargs) for cam in self.cameras])
804  if(AADTs == []): return None
805  else: return sum(AADTs)/float(len(AADTs))
806 
807  def exportToCode(self, moduleName='tvaMetaData', justifyCol1=55, justifyCol2=35):
808  ''' Dump this object's data as executable code. '''
809  camera_names = ["x.name=='"+x.name+"'" for x in self.cameras]
810  print("site_analyses.append("+moduleName+".SiteAnalysis(str([x.idx for x in cameras if "+(' and '.join(camera_names)).ljust(justifyCol1)+" and x.site.name=='"+(self.site.name+"']),").ljust(justifyCol2)+" startTimes='"+str(self.startTimes)+"', endTimes='"+str(self.endTimes)+"', zone='"+self.zone.write()+"', xy_bounds='"+self.xy_bounds.write()+"', cm_bounds='"+self.cm_bounds.write()+"', max_speed="+str(self.max_speed)+", virtual_loops='"+self.virtual_loops.write()+"', expansion_factors='"+self.hourly_expansion_factors.write()+"'))")
811 
812 
814  import cPickle as pickle
815  lowest_version = None
816  for saCam in self.cameras:
817  try:
818  with open(os.path.join(saCam.getBaseDirectory(), 'dmp.mp'), 'rb') as input_data:
819  s_version = pickle.load(input_data)
820  #TODO: Keep lowest version. not last
821  if(lowest_version): lowest_version = s_version.split()[0]
822  else: lowest_version = s_version.split()[0]
823  except: pass
824  return lowest_version
825 
826 
827 
831  def __init__(self, *nonOptionalArgs, **kwargs):
832  SQLlists.__init__(self, CameraType, tvaMetaData.CamType, nonOptionalArgs, dir=nonOptionalArgs[0].dir, filename=nonOptionalArgs[0].dbn, **kwargs)
833  return
834 
835 class CameraType(tvaLib.Constructors.SQLalchemyParser):
836  def __init__(self, camera, config):
837  self.config = config
838  self.idx = camera.idx
839  self.name = camera.name
840  self.resX = camera.resX
841  self.resY = camera.resY
842  self.frameRate = camera.frameRate
843  self.camera_matrix = camera.camera_matrix
844  self.dist_coeffs = camera.dist_coeffs
845  self.FOV = camera.FOV
846  self.freeScalingParameter = camera.freeScalingParameter
847  self.imageScalingFactor = camera.imageScalingFactor
848 
849 
850  self.camera_matrix = tvaLib.Constructors.SuperListParse(self.camera_matrix, dimension=2, datatype='other')
851  self.dist_coeffs = tvaLib.Constructors.SuperListParse(self.dist_coeffs, dimension=1, datatype='other')
852  return
853 
854  def getID(self): return self.idx
855  def getName(self): return self.name
856  def getResY(self): return self.resX
857  def getResX(self): return self.resY
858  def getFrameRate(self): return self.frameRate
859  def getFOV(self): return self.FOV
860  def getFreeScalingParam(self): return self.freeScalingParameter
861  def getImageScalingFactor(self): return self.imageScalingFactor
862  def getCamMatrix(self): return self.camera_matrix
863  def getDistCoeffs(self): return self.dist_coeffs
865  with open(os.path.join(self.config.temp_dir, tvaLib.Parse.clean_file_name('camera_matrix-'+str(self.config.dbn)[:-7]+'-'+str(self.idx)+'-'+str(self.name)+'.txt')), 'wb') as f:
866  for line in self.camera_matrix.data:
867  f.write(' '.join([str(x) for x in line])+'\n')
868  return os.path.join(self.config.temp_dir, tvaLib.Parse.clean_file_name('camera_matrix-'+str(self.config.dbn)[:-7]+'-'+str(self.idx)+'-'+str(self.name)+'.txt'))
870  with open(os.path.join(self.config.temp_dir, tvaLib.Parse.clean_file_name('dist_coeffs-'+str(self.config.dbn)[:-7]+'-'+str(self.idx)+'-'+str(self.name)+'.txt')), 'wb') as f:
871  f.write(' '.join([str(x) for x in self.dist_coeffs.data]))
872  return os.path.join(self.config.temp_dir, tvaLib.Parse.clean_file_name('dist_coeffs-'+str(self.config.dbn)[:-7]+'-'+str(self.idx)+'-'+str(self.name)+'.txt'))
873 
875  if(self.camera_matrix.data and self.dist_coeffs.data):
876  return ['--undistort','1',
877  '--intrinsic-camera-filename', self.getCamMatrixAsFile(),
878  '--distortion-coefficients', str(self.dist_coeffs.data[0]),
879  '--distortion-coefficients', str(self.dist_coeffs.data[1]),
880  '--distortion-coefficients', str(self.dist_coeffs.data[2]),
881  '--distortion-coefficients', str(self.dist_coeffs.data[3]),
882  '--distortion-coefficients', str(self.dist_coeffs.data[4])]
883  return []
884 
885 
888 class Alignments(tvaLib.Constructors.SuperListParse):
889  def __init__(self, input, sidewalks=[], bikepaths=[], dimension=3, corridorMinProximity=5.0, corridorMinContinuousDistance=20.0, connectorSearchDistance=2.5, intersectionDistanceFactor=1.5, localString='Alignment'):
890  tvaLib.Constructors.SuperListParse.__init__(self, input, dimension=dimension, datatype='point')
891  self.ranBB = False
892  self.corridorMinContinuousDistance = corridorMinContinuousDistance
893  self.corridorMinProximity = corridorMinProximity
894  self.connectorSearchDistance = connectorSearchDistance
895  self.intersectionDistanceFactor = intersectionDistanceFactor
896  self.SDR = SDR(self.data)
897  self.localString = localString
898  self.sidewalks = tvaLib.Constructors.SuperListParse(sidewalks, dimension=1, datatype='int')
899  self.bikepaths = tvaLib.Constructors.SuperListParse(bikepaths, dimension=1, datatype='int')
900  #Set types in children
901  for aIx in self.sidewalks: self.data[int(aIx)].type=1
902  for aIx in self.bikepaths: self.data[int(aIx)].type=2
903  return
904 
905  def setup(self, **kwargs):
906  self.corridorMinContinuousDistance = kwargs.get('corridorMinContinuousDistance',20.0)
907  self.corridorMinProximity = kwargs.get('corridorMinProximity',5.0)
908  self.connectorSearchDistance = kwargs.get('connectorSearchDistance',2.5)
909  self.intersectionDistanceFactor = kwargs.get('intersectionDistanceFactor',1.5)
910 
911  def addItem(self, data, a_type=0):
912  self.data.append(Alignment(data, a_type=a_type, id=len(self.data), localString='Alignment'))
913  return True
914 
915  #Filter alignment according to a boundingbox
916  def addAlignBB(self, boundingboxes):
917  for align in range(len(self)):
918  self[align].pos_bb = deepcopy(self[align].pos)
919  removalList = []
920  appendList = []
921  plists = [range(len(self[align])),range(len(self[align]))]
922  plists[1].reverse()
923  for plist in plists:
924  lastPoint = None
925  for point in plist:
926  #Check if point has entered bounding boxes
927  for bb in range(len(boundingboxes)):
928  if(tvaLib.Geo.pip(self[align].pos_bb[point][0],self[align].pos_bb[point][1],boundingboxes[bb])):
929  #Attempt to generate a midpoint
930  if(lastPoint):
931  polyInter = tvaLib.Geo.polyInter(lastPoint,self[align].pos_bb[point],boundingboxes[bb])
932  if(polyInter): appendList.append(polyInter[0])
933  else: appendList.append(None)
934  else: appendList.append(None)
935  break
936  else:
937  removalList.append(point)
938  lastPoint = self[align][point]
939  continue
940  break
941 
942  self[align].pos_bb = tvaFilter.dropObjects(self[align].pos_bb, removalList)
943  if(appendList):
944  if(appendList[0]):
945  self[align].pos_bb.reverse()
946  self[align].pos_bb.append(appendList[0])
947  self[align].pos_bb.reverse()
948  if(appendList[1]): self[align].pos_bb.append(appendList[1])
949 
950  self.ranBB = True
951  return True
952 
953  def getAlignIndexByName(self, name):
954  for laneIx in range(len(self.data)):
955  if(self.data[laneIx].name == name): return laneIx
956  return False
957 
958  def getLinks(self):
959  if(not hasattr(self, 'links')): self.genLinks()
960  return self.links
961 
963  if(userType and (self.sidewalks or self.bikepaths)):
964  #Pedestrians can only use pedestrian lanes
965  if(userType==2): return [self[int(align)] for align in self.sidewalks]
966  #Cyclists can use cycle tracks or roads
967 
968  elif(userType==4): return [self[int(align)] for align in self.bikepaths]+[self[align] for align in self.getOrdinaryAlignIndeces()]
969  #All other types can only use regular lanes
970  #TODO: becuase cyclists can't be tracked accuratly for the time being, we have to lump them together with cars
971  else: return [self[int(align)] for align in self.bikepaths]+[self[align] for align in self.getOrdinaryAlignIndeces()]
972  else: return [align for align in self]
973 
975  try: return self.ordinaryAlignments
976  except: return self.genOrdinaryAlignIndeces()
977 
979  self.ordinaryAlignments = [x for x in range(len(self)) if (float(x) not in self.bikepaths and float(x) not in self.sidewalks)]
980  return self.ordinaryAlignments
981 
982  def genOpposingDirections(self, matching=0.90, angleThreshold=120.0):
983  ''' Opposition of direction is defined by a matching percentage of
984  alignment vector segment pairs with an angle threshold greater than
985  angleThreshold. '''
986 
988  alignments = self.data
989  for align in range(len(alignments)):
990  for alignB in range(len(alignments)):
991  if(align <= alignB): continue
992  angles = []
993  for alignpIx in range(len(alignments[align])-1):
994  for alignBpIx in range(len(alignments[alignB])-1):
995  angles.append(tvaLib.Geo.vectorsToAngleDegCC(alignments[align][alignpIx+1][0]-alignments[align][alignpIx][0],
996  alignments[align][alignpIx+1][1]-alignments[align][alignpIx][1],
997  alignments[alignB][alignBpIx+1][0]-alignments[alignB][alignBpIx][0],
998  alignments[alignB][alignBpIx+1][1]-alignments[alignB][alignBpIx][1]))
999  # Convert large angles to inverse angles (355 -> 5)
1000  angles = [angle if angle<180.0 else 360.0-angle for angle in angles]
1001  # Check matching rate
1002  if(sum(angle > angleThreshold for angle in angles)/float(len(angles)) > matching): self.opposingDirections.append([align, alignB])
1003  return True
1004 
1006  ''' Returns the result of genOpposingDirections() '''
1007  if(not hasattr(self, 'opposingDirections')): self.genOpposingDirections()
1008  return self.opposingDirections
1009 
1010 
1011  def genLinks(self, connectorSearchDistance=None, intersectionDistanceFactor=None, allowOpposingDirections=False):
1012  ''' Search through alignments for possible connectors within connectorSearchDistance
1013 
1014  Links stored one-by-one in self.links[] as:
1015  0 1 2 3 4 5 6 7 8 9
1016  [type, align, align-x, align-y, align_S, align-snap, align-snap-x, align-snap-y, align-snap_S, length]
1017 
1018  where:
1019  type=0: leading connectors (Divergence from main branch)
1020  type=1: trailing connectors (Convergence to main branch)
1021  type=2: intertwining connectors (Convergence and divergence)
1022 
1023  Alignments that are facing each other in orientation of travel are
1024  ignored unless allowOpposingDirections is set to true.
1025  '''
1026  if(not connectorSearchDistance): connectorSearchDistance = self.connectorSearchDistance
1027  if(not intersectionDistanceFactor): intersectionDistanceFactor = self.intersectionDistanceFactor
1028 
1029  self.links = []
1030  alignments = self.data
1031  for align in range(len(alignments)):
1032  searchSplines = alignments[:align] + alignments[(align + 1):]
1033 
1034  resultLead = tvaLib.Geo.getNearestXYinSplineFromXY(alignments[align][0][0], alignments[align][0][1], searchSplines, searchPoint=-1, searchRadius=connectorSearchDistance)
1035  if(resultLead):
1036  match_align = resultLead[4]
1037  #Ignore corridors
1038  if([align, match_align] in self.getCorridors() or [match_align, align] in self.getCorridors()): continue
1039  #Ignore opposing directions
1040  if(not allowOpposingDirections and ([align, match_align] in self.getOpposingDirections() or [match_align, align] in self.getOpposingDirections())): continue
1041  if(match_align >= align): match_align += 1
1042  ss_spline_c = tvaLib.Geo.subsec_spline_dist_cumulative(alignments[align])
1043  self.links.append([0, align, alignments[align][0][0], alignments[align][0][1], 0, match_align, resultLead[1], resultLead[2], ss_spline_c[-1], resultLead[0]])
1044 
1045  resultTrail = tvaLib.Geo.getNearestXYinSplineFromXY(alignments[align][-1][0], alignments[align][-1][1], searchSplines, searchPoint=0, searchRadius=connectorSearchDistance)
1046  if(resultTrail):
1047  match_align = resultTrail[4]
1048  #Ignore corridors
1049  if([align, match_align] in self.getCorridors() or [match_align, align] in self.getCorridors()): continue
1050  #Ignore opposing directions
1051  if(not allowOpposingDirections and ([align, match_align] in self.getOpposingDirections() or [match_align, align] in self.getOpposingDirections())): continue
1052  if(match_align >= align): match_align += 1
1053  ss_spline_c = tvaLib.Geo.subsec_spline_dist_cumulative(alignments[align])
1054  self.links.append([1, align, alignments[align][-1][0], alignments[align][-1][1], ss_spline_c[-1], match_align, resultTrail[1], resultTrail[2], 0, resultTrail[0]])
1055 
1056  for alignB in range(len(alignments)):
1057  #Ignore corridors
1058  if([align, alignB] in self.getCorridors() or [alignB, align] in self.getCorridors()): continue
1059  #Ignore opposing directions
1060  if(not allowOpposingDirections and ([align, alignB] in self.getOpposingDirections() or [alignB, align] in self.getOpposingDirections())): continue
1061  if(align>=alignB): continue
1062  resultInter = tvaLib.Geo.searchSplineProximity(alignments[align], alignments[alignB], minProximity=connectorSearchDistance*intersectionDistanceFactor)
1063  if(resultInter): self.links.append([2, align, resultInter[1], resultInter[2], resultInter[3], alignB, resultInter[4], resultInter[5], resultInter[6], resultInter[0]])
1064 
1065  return True
1066 
1067  def getCorridors(self):
1068  ''' Returns the result of genCorridors() '''
1069  if(not hasattr(self, 'corridors')): self.genCorridors()
1070  return self.corridors
1071 
1072  def genCorridors(self, minProximity=None, minContinuousDistance=None, allowOpposingDirections=False):
1073  ''' Generate list of corridors containing the alignment indeces for the
1074  alignments which share minContinuousDistance continuous proximity.
1075 
1076  Generated:
1077  =======
1078  self.corridors -> [[align1,align2],...]
1079 
1080  Alignments that are facing each other in orientation of travel are
1081  ignored unless allowOpposingDirections is set to true.
1082  '''
1083  if(not minContinuousDistance): minContinuousDistance = self.corridorMinContinuousDistance
1084  if(not minProximity): minProximity = self.corridorMinProximity
1085 
1086  self.corridors = []
1087  alignments = self.data
1088  for alignA in range(len(alignments)):
1089  for alignB in range(len(alignments)):
1090  #Ignore opposing directions
1091  if(not allowOpposingDirections and ([alignA, alignB] in self.getOpposingDirections() or [alignB, alignA] in self.getOpposingDirections())): continue
1092  if(alignA >= alignB): continue
1093  result = tvaLib.Geo.searchSplineContinuousProximity(alignments[alignA], alignments[alignB], minProximity=minProximity, minContinuousDistance=minContinuousDistance)
1094  if(result): self.corridors.append([alignA,alignB])
1095  return True
1096 
1097  def genRouteTree(self):
1098  self.route = Route()
1099  self.route.startSearch(self.data, self.getLinks(), self.getCorridors())
1100  return True
1101 
1102  def getRouteTree(self):
1103  if(not hasattr(self, 'route')): self.genRouteTree()
1104  return self.route
1105 
1106  def getRouteDistHorizonByPos(self, ax, ay, bx, by, distHorizonA, distHorizonB):
1107  ''' Use this function to determine if the route tree of user a
1108  intersects with the route tree of user b to a certain depth for each
1109  user.
1110 
1111  This function is a data-collecting wrapper for the more efficient
1112  getRouteDistHorizonByPreCalc()
1113  '''
1114  [laneA, _, _, _, _, S_A, _] = tvaLib.Geo.getSYfromXY(ax,ay,self.data)
1115  [laneB, _, _, _, _, S_B, _] = tvaLib.Geo.getSYfromXY(bx,by,self.data)
1116 
1117  return self.getRouteDistHorizonByPreCalc(laneA, S_A, laneB, S_B, distHorizonA, distHorizonB)
1118 
1119  def getRouteDistHorizonByPreCalc(self, laneA, S_A, laneB, S_B, distHorizonA, distHorizonB):
1120  ''' This function is a child of getRouteDistHorizonByPos()
1121  It can be called directly with correspdonging data to leverage
1122  memory instead of consuming CPU cycles snapping X,Y positions.
1123  '''
1124  if(laneA == laneB or True in [laneA in x and laneB in x for x in self.getCorridors()]):
1125 
1127  if((S_B > S_A and S_B < S_A+distHorizonA) or (S_A > S_B and S_A < S_B+distHorizonB)): return True
1128  else: return False
1129  else:
1130  localTreeA = self.getRouteTree().goToChildPosition(laneA, S_A)
1131  localTreeB = self.getRouteTree().goToChildPosition(laneB, S_B)
1132  return localTreeA.intersectHorizon(localTreeB, distHorizonA, horizonMatch=distHorizonB)
1133 
1134 class Route(tvaLib.Constructors.Tree):
1135  def __init__(self, alignIx=None, connectorIx=None, level=0, parent=None, branch_length=0, upstreamVerificationDistance=0):
1136  ''' This is a recursive object representing a branch on a route
1137  tree with parent and child branches. A route is defined as a
1138  sequence of branch ids to follow throughout.
1139 
1140  Input:
1141  ======
1142  alignIx = Index of alignment corresponding to scenery alignment data
1143  connectorIx = Index of connector (link) corresponding to scenery connector data
1144  branch_length = Length of branch
1145  upstreamVerificationDistance = Start of branch along alignIx's spline (measured in S)
1146 
1147  '''
1148  self.branch_length = branch_length
1149  self.upstreamVerificationDistance = upstreamVerificationDistance
1150  self.alignIx = alignIx
1151  self.connectorIx = connectorIx
1152  tvaLib.Constructors.Tree.__init__(self, level, parent)
1153 
1154  def addBranch(self, **kwargs):
1155  ''' Add a new branhc to the tree. '''
1156  self.branches.append(Route(level=self.level+1, parent=self, **kwargs))
1157 
1158  def loopBackBranch(self, parentBranchPointer):
1159  ''' Add a pointer to a parent branch closing a loop in the tree.
1160  Counterpart of method: addBranch()
1161  '''
1162  self.branches.append(parentBranchPointer)
1163 
1164  def startSearch(self, alignments, links, corridors):
1165  ''' Starting point for tree generation.
1166  Counterpart of method: searchForChildBranches()
1167  '''
1168  for align in range(len(alignments)):
1169  self.addBranch(alignIx=align)
1170  self.branches[-1].searchForChildBranches(alignments, links, corridors)
1171  return True
1172 
1173  def searchForChildBranches(self, alignments, links, corridors):
1174  ''' Recursive function to search branches during tree generation.
1175  Counterpart of method: startSearch()
1176 
1177  Link connector type 0 is a divergence
1178  Link connector type 1 is a convergence
1179  Link connector type 2 is a convergence and divergence.
1180  '''
1181 
1182  if(self.level > route_recursion_hard_limit): return False
1183  for link in range(len(links)):
1184  #Skip parent links
1185  if(self.parent and self.parent.connectorIx == link): continue
1186 
1187 
1188  localAlignGroup=None
1189  for corridor in corridors:
1190  if(self.alignIx in corridor): localAlignGroup = corridor
1191  if(not localAlignGroup): localAlignGroup = [self.alignIx]
1192 
1193 
1194  if(links[link][1] in localAlignGroup and self.parent.alignIx != links[link][5] and self.upstreamVerificationDistance < links[link][4]):
1195  self.branch_length = links[link][4] - self.upstreamVerificationDistance
1196  opposingAlignIx = links[link][5]
1197  UVD = links[link][8]
1198  opposingUVD = links[link][4]
1199  elif(links[link][5] in localAlignGroup and self.parent.alignIx != links[link][1] and self.upstreamVerificationDistance < links[link][8]):
1200  self.branch_length = links[link][8] - self.upstreamVerificationDistance
1201  opposingAlignIx = links[link][1]
1202  UVD = links[link][4]
1203  opposingUVD = links[link][8]
1204  else: continue
1205 
1206 
1207  parentLooBackSearch = self.searchParentsForLoopBack(alignIx=self.alignIx, connectorIx=link, upstreamVerificationDistance=UVD)
1208  if(parentLooBackSearch is not False):
1209  self.loopBackBranch(parentLooBackSearch)
1210  continue
1211 
1212  self.addBranch(alignIx=opposingAlignIx, connectorIx=link, upstreamVerificationDistance=UVD)
1213  self.branches[-1].searchForChildBranches(alignments, links, corridors)
1214  if(links[link][0]==0 or links[link][0]==2):
1215 
1216  self.addBranch(alignIx=self.alignIx, connectorIx=link, upstreamVerificationDistance=opposingUVD)
1217  self.branches[-1].searchForChildBranches(alignments, links, corridors)
1218 
1219 
1220  if(not self.branches):
1221  ss_spline_c = tvaLib.Geo.subsec_spline_dist_cumulative(alignments[self.alignIx])
1222  self.branch_length = ss_spline_c[-1] - self.upstreamVerificationDistance
1223  return True
1224 
1225  def getCumDistance(self, lowestLevel=0):
1226  ''' Return cumulative distance between start of current branch and
1227  start of tree.
1228  '''
1229  if(self.parent and self.level > lowestLevel): return self.parent.getCumDistance()+self.branch_length
1230  else: return self.branch_length
1231 
1232  def searchTreeForChildPosition(self, alignment, S, path=[]):
1233  ''' From current branch, search child branches for path to location
1234  defined by alignment and curvilinear distance S. Path is only
1235  passed during internal recursion (do not call it).
1236 
1237  Output:
1238  =======
1239  Relative path to tip in the format of a list of branch indeces
1240  to traverse. E.g. [0,1,0,2] (four levels)
1241  '''
1242 
1243  if(len(path) > route_recursion_hard_limit): return False
1244 
1245  if(self.alignIx == alignment and self.upstreamVerificationDistance < S): return path
1246  for branch in range(len(self.branches)):
1247  searchResult = self.branches[branch].searchTreeForChildPosition(alignment, S, path=path+[branch])
1248  if(searchResult): return searchResult
1249  return False
1250 
1251  def goToChildPosition(self, alignment, S):
1252  ''' Returns the branch corresponding to alignment, S, reachable
1253  from the current branch (False otherwise).
1254  '''
1255  return self.goToBranch(self.searchTreeForChildPosition(alignment,S))
1256 
1257  def searchParentsForLoopBack(self, alignIx, connectorIx, upstreamVerificationDistance):
1258  if(self.level==0): return False
1259  if(self.parent.alignIx==alignIx and self.connectorIx==connectorIx and self.upstreamVerificationDistance==upstreamVerificationDistance): return self.parent
1260  else: return self.parent.searchParentsForLoopBack(alignIx, connectorIx, upstreamVerificationDistance)
1261 
1262  def intersectHorizon(self, routeMatch, horizonThis, horizonMatch=None):
1263  ''' With the current branch, verify with another branch (presumably
1264  from a different part of this' parent route tree) if there is
1265  overlap up to the defined horizon. '''
1266  if(not horizonMatch): horizonMatch = horizonThis
1267  pathsA = self.getPathsToBranchEnds()
1268  pathsB = routeMatch.getPathsToBranchEnds()
1269 
1270  alignsA = set()
1271  alignsA.add((self.alignIx,self.branch_length,self.upstreamVerificationDistance))
1272  for path in pathsA:
1273  traversal = self
1274  for branch in path:
1275  traversal = traversal.goToBranch([branch])
1276  if(not isinstance(traversal, Route) or (traversal.getCumDistance(lowestLevel=self.level) > horizonThis)): break
1277  alignsA.add((traversal.alignIx,traversal.branch_length,traversal.upstreamVerificationDistance))
1278  alignsB = set()
1279  alignsB.add((routeMatch.alignIx,routeMatch.branch_length,routeMatch.upstreamVerificationDistance))
1280  for path in pathsB:
1281  traversal = routeMatch
1282  for branch in path:
1283  traversal = traversal.goToBranch([branch])
1284  if(not isinstance(traversal, Route) or (traversal.getCumDistance(lowestLevel=routeMatch.level) > horizonMatch)): break
1285  alignsB.add((traversal.alignIx,traversal.branch_length,traversal.upstreamVerificationDistance))
1286  return True in [x in alignsB for x in alignsA]
1287 
1288  def printTree(self):
1289  ''' Prints human-readable schematic of the tree with values.
1290  '''
1291  print(self.level*'-'+'Align ('+str(self.alignIx)+') Con ('+str(self.connectorIx)+') B_Len ('+str(self.branch_length)+') UVD ('+str(self.upstreamVerificationDistance)+')')
1292  for branch in self.branches:
1293  if(branch.level < self.level): print(self.level*'-'+'Loopback to level '+str(branch.level))
1294  else: branch.printTree()
1295  return True
1296 
1297 
1298 class Alignment(tvaLib.Constructors.SuperPointList):
1299  def __init__(self, align_data, a_type=0, id=0, localString='Alignment'):
1300  ''' Alignment container class
1301 
1302  Input:
1303  ======
1304  localString: local name used to label Alignment objects
1305  id: global id of alignment at site
1306  a_type: 0=road, 1=sidewalk, 2=bikepath
1307  '''
1308  tvaLib.Constructors.SuperPointList.__init__(self, align_data)
1309  self.name = 'align_'+str(id)
1310  self.localString = localString
1311  self.id = id
1312  self.pos_bb = []
1313  self.S = [0.0]
1314  self.type = a_type
1315  for p in range(len(self.pos)):
1316  if(p+1 >= len(self.pos)):
1317  break
1318  self.S.append(self.S[-1]+m.sqrt((self.getXCoordinates()[p+1]-self.getXCoordinates()[p])**2+(self.getYCoordinates()[p+1]-self.getYCoordinates()[p])**2))
1319  return
1320 
1321  def getName(self): return self.name
1322  def getType(self): return self.type
1323  def getPrintName(self): return self.localString+' '+str(self.id+1)
1324  def getPrintShortName(self): return self.localString[:5]+' '+str(self.id+1)
1325  def getSCoordinates(self): return [point for point in self.S]
1326  def getXCoordinatesBB(self): return [point[0] for point in self.pos_bb]
1327  def getYCoordinatesBB(self): return [point[1] for point in self.pos_bb]
1328 
1329  def hasAlignBB(self):
1330  if(self.pos_bb): return True
1331  else: return False
1332 
1334  ''' Define user type probabilities for this alignment type. '''
1335  if(self.type==1): return {0:0.0, 1:0.05, 2:0.80, 4:0.15}
1336  elif(self.type==2): return {0:0.0, 1:0.05, 2:0.15, 4:0.80}
1337  else: return {0:0.0, 1:0.40, 2:0.20, 4:0.40}
1338 
1339 class SDR(tvaLib.Constructors.SuperList):
1340  def __init__(self, aligns_data, pavement_half_width=3, max_exit_region_size=10):
1341  ''' Generate sorties de route (run off the road) region. '''
1342  tvaLib.Constructors.SuperList.__init__(self)
1343 
1344  try:
1345  for align_data in aligns_data:
1346  # For each point
1347  poly_data = []
1348  # Right curb
1349  for pix in range(len(align_data)):
1350  if(pix==0): poly_data.append(tvaLib.Geo.orthogonal_point_extension(pavement_half_width, align_data[pix], align_data[pix+1]))
1351  elif(pix==len(align_data)-1): poly_data.append(tvaLib.Geo.orthogonal_point_extension(-pavement_half_width, align_data[pix], align_data[pix-1]))
1352  else: poly_data.append(tvaLib.Geo.orthogonal_point_extension(pavement_half_width, align_data[pix], align_data[pix+1], PN1=align_data[pix-1]))
1353  # Left curb
1354  for pix in list(reversed(range(len(align_data)))):
1355  if(pix==0): poly_data.append(tvaLib.Geo.orthogonal_point_extension(-pavement_half_width, align_data[pix], align_data[pix+1]))
1356  elif(pix==len(align_data)-1): poly_data.append(tvaLib.Geo.orthogonal_point_extension(pavement_half_width, align_data[pix], align_data[pix-1]))
1357  else: poly_data.append(tvaLib.Geo.orthogonal_point_extension(-pavement_half_width, align_data[pix], align_data[pix+1], PN1=align_data[pix-1]))
1358  self.data.append(SDRpoly(poly_data))
1359  except: raise Exception, [392, 'Critical error encountered with alignment data (at coordinate "'+str(align_data[pix])+'") while building SDR alignment boundaries. Consider flushing the corresponding alignment data and rebuilding it.']
1360 
1361 class SDRpoly(tvaLib.Constructors.SuperPointList):
1362  def __init__(self, poly_data):
1363  tvaLib.Constructors.SuperPointList.__init__(self, poly_data)
1364 
1365 
1369  def __init__(self, offset=0):
1370  self.phases = []
1371  self.offset = offset
1372 
1373  def add(self, *args, **kwargs):
1374  self.phases.append(*args, **kwargs)
1375 
1376 
1378  def __init__(self, green=5.0, yellow=3.0, allred=1.0, locations=[]):
1379  self.green = green
1380  self.yellow = yellow
1381  self.allred = allred
1382  self.locations = locations
1383 
1384  def addLocation(self, lane, s):
1385  self.locations.append({'lane':lane,'s':s})
1386 
1387 
1388 
1389 
1393  def __init__(self, coordinates='', nLanes=1, radius=3, days=1, expansionFactors=False):
1394  self.coordinates = tvaLib.Constructors.SuperListParse(coordinates)
1395 
1396  self.loops = len(self.coordinates)
1397  self.lanes = nLanes
1398  self.radius = radius
1399  self.edge_hourly = [[[[0,[]],[0,[]]] for x in range(nLanes)] for x in range(24*days)]
1400  self.edge_m15 = [[[[0,[]],[0,[]]] for x in range(nLanes)] for x in range(24*days*4)]
1401  self.coord_hourly = [[[0,[]] for x in range(len(self.coordinates))] for x in range(24*days)]
1402  self.coord_m15 = [[[0,[]] for x in range(len(self.coordinates))] for x in range(24*days*4)]
1403  return
1404 
1405  def __len__(self): return len(self.coord_hourly)
1406  def __getitem__(self,i): return self.coord_hourly[i]
1407  def __repr__(self): return self.__class__.__name__+' '+str(self.coordinates)
1408  def __str__(self): return self.__class__.__name__+' '+str(self.coordinates)
1409  def __iter__(self): return iter(self.coordinates)
1410  def __add__(self, slist): self.coordinates += slist.coordinates; return None
1411  def append(self,value): return self.coordinates.append(value)
1412  def reverse(self): self.coordinates.reverse();return None
1413  def count(self, value): return self.coordinates.count(value)
1414  def index(self, value): return self.coordinates.index(value)
1415 
1416  def addCoordCounts(self, objects, start=0, fps=15, verbose=0):
1417  ''' Add counts and speeds from virtual loop coordinates.
1418 
1419  Input:
1420  ======
1421  objects: a nested camera/sequence ObjectSpace
1422  '''
1423  if(not objects.getAll()): return False
1424  if(verbose >= 2): print(' Compiling virtual loop counts...')
1425  for loop in range(self.loops):
1426  for camIx in range(len(objects)):
1427  for fileIx in range(len(objects[camIx])):
1428  for i in range(len(objects[camIx][fileIx])):
1429  obj = objects[camIx][fileIx][i]
1430  t = 0
1431  for point in obj.getPositions():
1432  if(m.sqrt(pow(point.x-self.coordinates[loop].x,2)+pow(point.y-self.coordinates[loop].y,2)) < self.radius):
1433  time_h = int(m.floor(float(obj.getFirstInstant()+t)/fps/60/60))
1434  time_m15 = int(m.floor(float(obj.getFirstInstant()+t)/fps/60/15))
1435  self.coord_hourly[objects[camIx].metadatas[fileIx].getHour()+time_h][loop][0] += 1
1436  self.coord_hourly[objects[camIx].metadatas[fileIx].getHour()+time_h][loop][1].append(obj.velocities.positions[2][t])
1437  self.coord_m15[objects[camIx].metadatas[fileIx].getHour()*4+objects[camIx].metadatas[fileIx].getMinute()/15+time_m15][loop][0] += 1
1438  self.coord_m15[objects[camIx].metadatas[fileIx].getHour()*4+objects[camIx].metadatas[fileIx].getMinute()/15+time_m15][loop][1].append(obj.velocities.positions[2][t])
1439  break
1440  t += 1
1441  return True
1442 
1443  def addEdgeCounts(self, objects, fps=15, verbose=0):
1444  ''' Add counts and speeds from edge of mask (in/out lanes).
1445 
1446  Input:
1447  ======
1448  objects: a nested camera/sequence ObjectSpace
1449  '''
1450  if(not objects.getAll()): return False
1451  if(verbose >= 2): print(' Compiling edge counts...')
1452  for camIx in range(len(objects)):
1453  for fileIx in range(len(objects[camIx])):
1454  for i in range(len(objects[camIx][fileIx])):
1455  obj = objects[camIx][fileIx][i]
1456  time_h_in = int(m.floor(float(obj.timeInterval.first)/fps/60/60))
1457  time_h_out = int(m.floor(float(obj.timeInterval.last)/fps/60/60))
1458  time_m15_in = int(m.floor(float(obj.timeInterval.first)/fps/60/15))
1459  time_m15_out = int(m.floor(float(obj.timeInterval.last)/fps/60/15))
1460  try:
1461  self.edge_hourly[objects[camIx].metadatas[fileIx].getHour()+time_h_in][obj.curvilinearPositions.getLanes()[0]][0][0] += 1
1462  self.edge_hourly[objects[camIx].metadatas[fileIx].getHour()+time_h_out][obj.curvilinearPositions.getLanes()[-1]][1][0] += 1
1463  self.edge_hourly[objects[camIx].metadatas[fileIx].getHour()+time_h_in][obj.curvilinearPositions.getLanes()[0]][0][1].append(obj.velocities.positions[2][0])
1464  self.edge_hourly[objects[camIx].metadatas[fileIx].getHour()+time_h_out][obj.curvilinearPositions.getLanes()[-1]][1][1].append(obj.velocities.positions[2][-1])
1465  self.edge_m15[objects[camIx].metadatas[fileIx].getHour()*4+objects[camIx].metadatas[fileIx].getMinute()/15+time_m15_in][obj.curvilinearPositions.getLanes()[0]][0][0] += 1
1466  self.edge_m15[objects[camIx].metadatas[fileIx].getHour()*4+objects[camIx].metadatas[fileIx].getMinute()/15+time_m15_out][obj.curvilinearPositions.getLanes()[-1]][1][0] += 1
1467  self.edge_m15[objects[camIx].metadatas[fileIx].getHour()*4+objects[camIx].metadatas[fileIx].getMinute()/15+time_m15_in][obj.curvilinearPositions.getLanes()[0]][0][1].append(obj.velocities.positions[2][0])
1468  self.edge_m15[objects[camIx].metadatas[fileIx].getHour()*4+objects[camIx].metadatas[fileIx].getMinute()/15+time_m15_out][obj.curvilinearPositions.getLanes()[-1]][1][1].append(obj.velocities.positions[2][-1])
1469  except AttributeError: raise Exception, [2056, 'Attempting to compile edge counts from non-existant curvilinear data for object num '+str(obj.num)+' in '+objects.metadatas[camIx].site.name+'/'+objects.metadatas[camIx].name+'/'+objects[camIx].metadatas[fileIx].name+'.']
1470  #if(verbose):
1471  # print(' Compilation report: Average objects per non-empty lane: '+str(format(sum(self.edgeChunks[-1])/len(np.nonzero(vl)[1]))))
1472  # print(' Compilation report: Missing objects report: '+str(format(m.fabs(vl[0,:].sum()-vl[1,:].sum()))))
1473  return True
1474 
1475  def getCoordCounts(self, i=[0,None], id=[0,None], m='hour'):
1476  if(m=='hour'): source = self.coord_hourly
1477  else: source = self.coord_m15
1478 
1479  if(type(i) == int): i = [i,i+1]
1480  if(type(id) == int): id = [id,id+1]
1481 
1482  r = 0
1483  for j,v in enumerate(source[i[0]:i[1]]):
1484  for k,w in enumerate(v[id[0]:id[1]]):
1485  r += w[0]
1486  return r
1487 
1488  def getEdgeCounts(self, i=[0,None], lane=[0,None], side=0, m='hour'):
1489  if(m=='hour'): source = self.edge_hourly
1490  else: source = self.edge_m15
1491 
1492  if(type(i) == int): i = [i,i+1]
1493  if(type(lane) == int): lane = [lane,lane+1]
1494 
1495  r = 0
1496  for j,v in enumerate(source[i[0]:i[1]]):
1497  for k,w in enumerate(v[lane[0]:lane[1]]):
1498  r += w[side][0]
1499  return r
1500 
1501  def getCoordCountVector(self, i=[0,None], m='hour'):
1502  r = []
1503  for j in range(self.loops):
1504  r.append(self.getCoordCounts(i=i, id=j, m=m))
1505  return r
1506 
1507  def getEdgeCountVector(self, i=[0,None], m='hour'):
1508  r = []
1509  for j in range(self.lanes):
1510  r.append(self.getEdgeCounts(i=i, lane=j, side=0, m=m))
1511  for j in range(self.lanes):
1512  r.append(self.getEdgeCounts(i=i, lane=j, side=1, m=m))
1513  return r
1514 
1515  def getCoordMeanSpeed(self, i=[0,None], id=[0,None], m='hour'):
1516  if(m=='hour'): source = self.coord_hourly
1517  else: source = self.coord_m15
1518 
1519  if(type(i) == int): i = [i,i+1]
1520  if(type(id) == int): id = [id,id+1]
1521 
1522  r = []
1523  for j,v in enumerate(source[i[0]:i[1]]):
1524  for k,w in enumerate(v[id[0]:id[1]]):
1525  r += w[1]
1526 
1527  if(len(r)==0): return 0
1528  return sum(r)/self.getCoordCounts(i=i, id=id, m=m)
1529 
1530  def getEdgeMeanSpeed(self, i=[0,None], lane=[0,None], side=0, m='hour'):
1531  if(m=='hour'): source = self.edge_hourly
1532  else: source = self.edge_m15
1533 
1534  if(type(i) == int): i = [i,i+1]
1535  if(type(lane) == int): lane = [lane,lane+1]
1536 
1537  r = []
1538  for j,v in enumerate(source[i[0]:i[1]]):
1539  for k,w in enumerate(v[lane[0]:lane[1]]):
1540  r += w[side][1]
1541 
1542  if(len(r)==0): return 0
1543  return sum(r)/self.getEdgeCounts(i=i, lane=lane, side=side, m=m)
1544 
1545  def getCoordMeanSpeedVector(self, i=[0,None], m='hour'):
1546  r = []
1547  for j in range(self.loops):
1548  r.append(self.getCoordMeanSpeed(i=i, id=j, m=m))
1549  return r
1550 
1551  def getEdgeMeanSpeedVector(self, i=[0,None], m='hour'):
1552  r = []
1553  for j in range(self.lanes):
1554  r.append(self.getEdgeMeanSpeed(i=i, lane=j, side=0, m=m))
1555  for j in range(self.lanes):
1556  r.append(self.getEdgeMeanSpeed(i=i, lane=j, side=1, m=m))
1557  return r
1558 
1559  def write(self):
1560  ''' This should be called from the parent object in order to store the
1561  data properly in a DB using SQLAlchemy.
1562  '''
1563  storage_value = []
1564  for data in self.coordinates:
1565  storage_value.append(data.write())
1566  return_val = '['+','.join(map(str, storage_value))+']'
1567 
1568  if(return_val == '[]'): return ''
1569  else: return return_val
1570 
1571 
1572 
1575 
1577  ''' This is a map of all object's existance in any frame
1578  '''
1579  def __init__(self, objects):
1580 
1581  self.lastFrame = 0
1582  if(objects is not None):
1583  for object_ in objects:
1584  if(object_.getLastInstant() > self.lastFrame): self.lastFrame = object_.getLastInstant()
1585 
1586  self.table = [[] for x in range(self.lastFrame)]
1587  if(objects is not None):
1588  for object_ in objects:
1589  for x in object_.getTimeInterval():
1590  self.table[x-1].append(object_.num)
1591  return
1592 
1593  def getExposureAtInstant(self, t, frames=300):
1594  return len(list(set(tvaLib.flatten_list(self.table[max(0,t-int(frames/2.0)):min(len(self.table),t+int(frames/2.0))]))))
1595 
1596 
1599 class ObjectSpace(tvaLib.Constructors.SuperList):
1600  def __init__(self, spaceType='cameras', **kwargs):
1601  ''' Contains objects lists in memory.
1602 
1603  Space types include:
1604  ====================
1605  sites
1606  cameras
1607  sequences
1608  '''
1609  tvaLib.Constructors.SuperList.__init__(self, **kwargs)
1610  self.spaceType = spaceType
1611  self.idxs = []
1612  self.metadatas = []
1613  return
1614 
1615  def add(self, objects, idx=0, framerate=None, metadata=None):
1616  ''' Add framerate to individual objects in order to track data later on
1617  when objects become mixed.
1618  '''
1619  if(framerate):
1620  for obj in objects: obj.framrate = framerate
1621  self.idxs.append(idx)
1622  self.metadatas.append(metadata)
1623  self.data.append(objects)
1624  if(type(objects) is list): self.hashTable = [obj.hash for obj in objects]
1625  return True
1626 
1627  def getAll(self):
1628  return_ = []
1629  for data in self.data:
1630  if(type(data) is list): return_ += data
1631  else: return_ += data.getAll()
1632  return return_
1633 
1634  def getAllSpeeds(self, flatList=False, averagePerUser=False):
1635  return_ = []
1636  for data in self.data:
1637  if(type(data) is list):
1638  if(averagePerUser): return_ += [sum(x.getSpeeds())/float(len(x.getSpeeds())) for x in data]
1639  else: return_ += [list(x.getSpeeds()) for x in data]
1640  else: return_ += data.getAllSpeeds(flatList=flatList)
1641  if(flatList): return tvaLib.flatten_list(return_)
1642  else: return return_
1643 
1644  def getObjByHash(self, hash_):
1645  for data in self.data:
1646  if(type(data) is list): return data[self.hashTable.index(hash_)]
1647  else:
1648  search = data.getObjByHash(hash_)
1649  if(search): return search
1650  return False
1651 
1652  def getSubSpacebyId(self, id):
1653  for dataIx in range(len(self.metadatas)):
1654  if(id==self.metadatas[dataIx].idx): return self.data[dataIx]
1655  return None
1656 
1657 
1658  def getSubSpacebyTime(self, start, end):
1659  ''' Returns any object with a START TIME within a start and end time.
1660  Expects start and end to be datetime.time() objects.
1661  TODO: Add support for dates as well. '''
1662  objects = []
1663  for metadata,objs in self.iterateSequences():
1664  for obj in objs:
1665  objStartTime = metadata.getStartTime()+timedelta(seconds=obj.getFirstInstant()/float(metadata.cameraView.camera.frameRate))
1666  if(start < objStartTime.time() and objStartTime.time() < end):
1667  objects.append(obj)
1668  return objects
1669 
1670  def iterateSequences(self):
1671  ''' iterate over sequences
1672  TODO: Needs more work to be generalised. '''
1673  metadata = []
1674  data = []
1675 
1676  if(self.spaceType == 'sequences'):
1677  for i in range(len(self)):
1678  metadata.append(self.metadatas[i])
1679  data.append(self.data[i])
1680  elif(self.spaceType == 'cameras'):
1681  for i in range(len(self)):
1682  for j in range(len(self.data[i])):
1683  metadata.append(self.data[i].metadatas[j])
1684  data.append(self.data[i][j])
1685  return zip(metadata,data)
1686 
1687 
1688 class UPSpace(tvaLib.Constructors.SuperList):
1689  def __init__(self, spaceType='cameras', **kwargs):
1690  ''' Contains userPair lists in memory.
1691 
1692  Space types include:
1693  ====================
1694  sites
1695  cameras
1696  sequences
1697  '''
1698  tvaLib.Constructors.SuperList.__init__(self, **kwargs)
1699  self.spaceType = spaceType
1700  self.idxs = []
1701  self.metadatas = []
1702  return
1703 
1704  def add(self, userPairs, idx=0, metadata=None):
1705  self.idxs.append(idx)
1706  self.metadatas.append(metadata)
1707  self.data.append(userPairs)
1708  return True
1709 
1710  def getAll(self):
1711  from lib.int import UserPairs
1712  return_ = UserPairs([])
1713  for data in self.data:
1714  if(data is None): return None
1715  elif(data.__class__ != UPSpace): return_ + data
1716  else:
1717  d = data.getAll()
1718  if(d): return_ + d
1719  else: return None
1720  return return_
1721 
1722  def getSubSpacebyId(self, id):
1723  for dataIx in range(len(self.metadatas)):
1724  if(id==self.metadatas[dataIx].idx): return self.data[dataIx]
1725  return None
1726 
1727 class DroppedObjectTypes(tvaLib.Constructors.SuperList):
1728  def __init__(self, types=['ie', 'bb', 'te', 'tc']):
1729  self.data = {}
1730  for t in types:
1731  self.data[t] = ObjectSpace()
1732  return
1733 
1734  def addByType(self, type_, objects):
1735  self.data[type_].add(objects)
1736  return True
1737 
1738  def merge(self, droppedObjectTypes):
1739  for i in self.data:
1740  if(i in droppedObjectTypes): self.data[i].add(droppedObjectTypes[i])
1741  for i in droppedObjectTypes:
1742  if(i not in self.data):
1743  if(self.data == {}): self.data = {i:droppedObjectTypes[i]}
1744  else: self.data[i] = droppedObjectTypes[i]
1745  return True
def getAll(self)
Definition: scene.py:1627
def setup(self, kwargs)
Definition: scene.py:905
def __init__(self, nonOptionalArgs, kwargs)
Definition: scene.py:89
def getObjByHash(self, hash_)
Definition: scene.py:1644
def getWeekday(self)
Definition: scene.py:474
def getClassificationTrainingBaseDirectory(self, type)
Definition: scene.py:285
crossStreet1
Update standardised meta data if it exists.
Definition: scene.py:130
def getAll(self)
Definition: scene.py:1710
Declare camera type object.
Definition: scene.py:830
Generic.
Definition: scene.py:30
def exportToCode(self, moduleName='tvaMetaData')
Definition: scene.py:502
Definition: int.py:1
def getName(self)
Definition: scene.py:1321
def startSearch(self, alignments, links, corridors)
Definition: scene.py:1164
def getLinks(self)
Definition: scene.py:958
def add(self, userPairs, idx=0, metadata=None)
Definition: scene.py:1704
def __init__(self, nonOptionalArgs, kwargs)
Definition: scene.py:831
def getEdgeCountVector(self, i=[0, None, m='hour')
Definition: scene.py:1507
def getFullCameraCalibrationFilename(self)
Definition: scene.py:294
def goToChildPosition(self, alignment, S)
Definition: scene.py:1251
Declare alignment object type.
Definition: scene.py:888
def __len__(self)
Definition: scene.py:613
def getFullHomographyFilename(self, force=False)
Definition: scene.py:286
def getResX(self)
Definition: scene.py:857
def getEdgeMeanSpeedVector(self, i=[0, None, m='hour')
Definition: scene.py:1551
def setCountExpInstancesWInd(self, value)
Definition: scene.py:494
def addByType(self, type_, objects)
Definition: scene.py:1734
lastFrame
Grab last frame.
Definition: scene.py:1581
def setCountExpInstances(self, value)
Definition: scene.py:492
def getFullSatFilename(self)
Definition: scene.py:176
def getOrdinaryAlignIndeces(self)
Definition: scene.py:974
def getRouteDistHorizonByPreCalc(self, laneA, S_A, laneB, S_B, distHorizonA, distHorizonB)
Definition: scene.py:1119
def append(self, value)
Definition: scene.py:1411
Declare traffic_controller object.
Definition: scene.py:1368
def setCountExpPairsWInd(self, value)
Definition: scene.py:493
def join(obj1, obj2, postSmoothing=True)
Definition: tools_obj.py:816
def setCountsFromObjects(self, objects)
Definition: scene.py:485
def getAADT(self, hourly_expansion_factors, doweek_expansion_factors, monthly_expansion_factors, kwargs)
Definition: scene.py:367
def getPrintShortName(self)
Definition: scene.py:1324
def __init__(self, align_data, a_type=0, id=0, localString='Alignment')
Definition: scene.py:1299
def getFullMaskFilename(self)
Definition: scene.py:299
def getNamedClusters(self)
Definition: scene.py:581
def setCountExpPairs(self, value)
Definition: scene.py:491
def getDurationUnit(self)
Definition: scene.py:392
upstreamVerificationDistance
Definition: scene.py:1149
def add(self, objects, idx=0, framerate=None, metadata=None)
Definition: scene.py:1615
def getSubSpacebyId(self, id)
Definition: scene.py:1722
def __init__(self, scene, config)
Definition: scene.py:209
def getCamSeqs_AMPM(self)
Definition: scene.py:763
def intersectHorizon(self, routeMatch, horizonThis, horizonMatch=None)
Definition: scene.py:1262
def __init__(self, alignIx=None, connectorIx=None, level=0, parent=None, branch_length=0, upstreamVerificationDistance=0)
Definition: scene.py:1135
def iterateSequences(self)
Definition: scene.py:1670
def setHomography(self, value)
Definition: scene.py:279
def getCombinedMasks(self)
Definition: scene.py:178
def setDuration(self, value)
Definition: scene.py:495
def getDuration(self)
Definition: scene.py:477
branch_length
Hard limit on recursion:
Definition: scene.py:1148
def printTree(self)
Definition: scene.py:1288
def getAADT(self, hourly_expansion_factors=None, doweek_expansion_factors=None, monthly_expansion_factors=None, kwargs)
Definition: scene.py:795
def getAADT(self, hourly_expansion_factors, doweek_expansion_factors, monthly_expansion_factors, kwargs)
Definition: scene.py:192
def getUndistortCmdStack(self)
Definition: scene.py:874
def getOpposingDirections(self)
Definition: scene.py:1005
def getYear(self)
Definition: scene.py:468
def __init__(self, coordinates='', nLanes=1, radius=3, days=1, expansionFactors=False)
Definition: scene.py:1393
def getCombinedMasks(self)
Definition: scene.py:744
def getFOV(self)
Definition: scene.py:859
def getADT(self, hourly_expansion_factors, exposure='traffic', customCount=None, customHour=None, kwargs)
Definition: scene.py:308
def write(self, scene)
Definition: scene.py:241
def count(self, value)
Definition: scene.py:1413
def getGridHexSize(self)
Definition: scene.py:741
def setRotation(self, value)
Definition: scene.py:496
def getYCoordinatesBB(self)
Definition: scene.py:1327
def getEndTime(self)
Definition: scene.py:303
def getPrintName(self)
Definition: scene.py:1323
Declare analysis objects.
Definition: scene.py:573
def getFrameRate(self)
Definition: scene.py:858
def getBaseDirectory(self)
Definition: scene.py:95
def getID(self)
Definition: scene.py:854
def __init__(self, site, config, kwargs)
Definition: scene.py:114
def index(self, value)
Definition: scene.py:1414
def getCoordMeanSpeed(self, i=[0, None, id=[0, None, m='hour')
Definition: scene.py:1515
def objectFromDict(idx=0, kwargs)
Definition: scene.py:71
def __init__(self, analysis, config)
Definition: scene.py:624
def addItem(self, data, a_type=0)
Definition: scene.py:911
def addBranch(self, kwargs)
Definition: scene.py:1154
cameraCalibrationFilename
Definition: scene.py:217
def exportToCode(self, moduleName='tvaMetaData', justifyCol1=20, justifyCol2=35, recursive=True)
Definition: scene.py:397
def getExposureAtInstant(self, t, frames=300)
Definition: scene.py:1593
Declare Scene descriptor object.
Definition: scene.py:208
def __init__(self, nonOptionalArgs, kwargs)
Definition: scene.py:619
def getCumDistance(self, lowestLevel=0)
Definition: scene.py:1225
def getDuration(self)
Definition: scene.py:389
def getEndTime(self)
Definition: scene.py:750
Objects References.
Definition: scene.py:1576
def loopBackBranch(self, parentBranchPointer)
Definition: scene.py:1158
def addAlignBB(self, boundingboxes)
Definition: scene.py:916
def write(self, site_analysis)
Definition: scene.py:701
def getCamMatrixAsFile(self)
Definition: scene.py:864
def getMinute(self)
Definition: scene.py:472
alignIx
Hard limit on recursion:
Definition: scene.py:1150
def genLinks(self, connectorSearchDistance=None, intersectionDistanceFactor=None, allowOpposingDirections=False)
Definition: scene.py:1011
def __init__(self, cluster, config)
Definition: scene.py:588
def __init__(self, sequence, config)
Definition: scene.py:406
def merge(self, droppedObjectTypes)
Definition: scene.py:1738
def write(self, site)
Definition: scene.py:159
def getCorridors(self)
Definition: scene.py:1067
def getADT(self, hourly_expansion_factors, kwargs)
Definition: scene.py:184
config
Metadata.
Definition: scene.py:408
def __init__(self, nonOptionalArgs, kwargs)
Definition: scene.py:574
def getBaseDirectory(self)
Definition: scene.py:175
def getCamSeqs(self)
Definition: scene.py:745
def getNamedClusterByidx(self, idx)
Definition: scene.py:578
def getFullConfigurationFilename(self, analysis='Analysis')
Definition: scene.py:737
def getName(self)
Definition: scene.py:855
def getDuration(self)
Definition: scene.py:748
table
Generate table.
Definition: scene.py:1586
def exportToCode(self, moduleName='tvaMetaData', justifyCol1=55, justifyCol2=35)
Definition: scene.py:807
def getNamedClusterByName(self, name)
Definition: scene.py:579
def genCorridors(self, minProximity=None, minContinuousDistance=None, allowOpposingDirections=False)
Definition: scene.py:1072
def __str__(self)
Definition: scene.py:1408
def __init__(self, camera, config)
Definition: scene.py:836
def getFullEventsFilename(self)
Definition: scene.py:440
homographyDistanceUnit
Definition: scene.py:216
def loadAnnotations(self, forceNonGTFilename=False, indent=0, legacy=False, verbose=0)
Definition: scene.py:546
def getSecond(self)
Definition: scene.py:473
def getXCoordinatesBB(self)
Definition: scene.py:1326
def getAlignIndexByName(self, name)
Definition: scene.py:953
def getSubSpacebyTime(self, start, end)
Definition: scene.py:1658
def exportToCode(self, moduleName='tvaMetaData', justifyCol1=35, justifyCol2=10, recursive=True)
Definition: scene.py:200
def getFullEventsCSVFilename(self)
Definition: scene.py:441
def getFullClassifiedFilename(self)
Definition: scene.py:437
defaultFullCfgFilename
Setup defaults from config.
Definition: scene.py:219
Objects containers.
Definition: scene.py:1599
def __init__(self, nonOptionalArgs, kwargs)
Definition: scene.py:633
def getAllSpeeds(self, flatList=False, averagePerUser=False)
Definition: scene.py:1634
def getFullConfigurationFilename(self)
Definition: scene.py:295
def __init__(self, aligns_data, pavement_half_width=3, max_exit_region_size=10)
Definition: scene.py:1340
def __len__(self)
Definition: scene.py:1405
def __repr__(self)
Definition: scene.py:1407
def __init__(self, poly_data)
Definition: scene.py:1362
def new(self, sqlFields={}, classFields)
Definition: scene.py:50
def write(self, sequence)
Definition: scene.py:456
def __getitem__(self, i)
Definition: scene.py:612
def searchParentsForLoopBack(self, alignIx, connectorIx, upstreamVerificationDistance)
Definition: scene.py:1257
def addLocation(self, lane, s)
Definition: scene.py:1384
def loadObjects(self, filename_override='', max_obj=None, max_obj_features=999, suppress_features=False, load_gt=False, indent=0, verbose=0)
Definition: scene.py:505
def getStartTime(self)
Definition: scene.py:300
def setTranslation(self, x, y)
Definition: scene.py:497
legacy
Internal data.
Definition: scene.py:420
def getDistCoeffsAsFile(self)
Definition: scene.py:869
def isParallelSequenceTo(self, sequence, maxDiffSec=60)
Definition: scene.py:479
def update(self)
Definition: scene.py:57
def getImageScalingFactor(self)
Definition: scene.py:861
def setCountObjOld(self, value)
Definition: scene.py:490
def getRestrictedAlignmentsByClassification(self, userType)
Definition: scene.py:962
def getCoordCountVector(self, i=[0, None, m='hour')
Definition: scene.py:1501
def __init__(self, green=5.0, yellow=3.0, allred=1.0, locations=[])
Definition: scene.py:1378
def findLowestMPversion(self)
Definition: scene.py:813
def getDay(self)
Definition: scene.py:470
def __init__(self, input, sidewalks=[], bikepaths=[], dimension=3, corridorMinProximity=5.0, corridorMinContinuousDistance=20.0, connectorSearchDistance=2.5, intersectionDistanceFactor=1.5, localString='Alignment')
Definition: scene.py:889
def getCamSeqs_Hourly(self)
Definition: scene.py:753
def getFullSerialisedFilename(self)
Definition: scene.py:436
def getMonth(self)
Definition: scene.py:469
def addCoordCounts(self, objects, start=0, fps=15, verbose=0)
Definition: scene.py:1416
def exportToCode(self, moduleName='tvaMetaData', recursive=True)
Definition: scene.py:97
def setCountObjects(self, value)
Definition: scene.py:488
def getRouteDistHorizonByPos(self, ax, ay, bx, by, distHorizonA, distHorizonB)
Definition: scene.py:1106
def genOpposingDirections(self, matching=0.90, angleThreshold=120.0)
Definition: scene.py:982
def getCoordMeanSpeedVector(self, i=[0, None, m='hour')
Definition: scene.py:1545
def add(self, args, kwargs)
Definition: scene.py:1373
configurationFilename
Definition: scene.py:218
def searchForChildBranches(self, alignments, links, corridors)
Definition: scene.py:1173
def getCountObjOld(self)
Definition: scene.py:386
def __iter__(self)
Definition: scene.py:1409
def getBaseDirectory(self)
Definition: scene.py:284
def getType(self)
Definition: scene.py:1322
def setCountUserType(self, value, i)
Definition: scene.py:489
Generate site database.
Definition: scene.py:88
alignments
Create and link abstract objects from data.
Definition: scene.py:125
def addEdgeCounts(self, objects, fps=15, verbose=0)
Definition: scene.py:1443
def getCamMatrix(self)
Definition: scene.py:862
def getStartTime(self)
Definition: scene.py:475
def getFullDataFilename(self)
Definition: scene.py:435
def __iter__(self)
Definition: scene.py:614
def getCamSeqsInInterval(self, i)
Definition: scene.py:773
def hasAlignBB(self)
Definition: scene.py:1329
def getCountObjects(self)
Definition: scene.py:383
def __add__(self, slist)
Definition: scene.py:1410
def getDistCoeffs(self)
Definition: scene.py:863
def __init__(self, site_analysis, config, sites=None)
Definition: scene.py:638
def getSCoordinates(self)
Definition: scene.py:1325
def getDurationUnit(self)
Definition: scene.py:747
def getFullVideoFilename(self, forceDistorted=False, allowNonExistant=False)
Definition: scene.py:442
def __init__(self, class_prototype, sql_prototype, nonOptionalArgs, dir='', filename='scene.sqlite', kwargs)
Definition: scene.py:31
def getADT(self, hourly_expansion_factors=None, kwargs)
Definition: scene.py:785
def genOrdinaryAlignIndeces(self)
Definition: scene.py:978
Declare Scene descriptor object.
Definition: scene.py:405
def getFullAnnotationFilename(self)
Definition: scene.py:439
def getFreeScalingParam(self)
Definition: scene.py:860
def getFullGroundTruthFilename(self)
Definition: scene.py:438
def getRouteTree(self)
Definition: scene.py:1102
def getAlchemyObject(self, idx)
Definition: scene.py:80
def getEdgeMeanSpeed(self, i=[0, None, lane=[0, None, side=0, m='hour')
Definition: scene.py:1530
def getEdgeCounts(self, i=[0, None, lane=[0, None, side=0, m='hour')
Definition: scene.py:1488
Declare site descriptor object.
Definition: scene.py:113
def getStartTime(self)
Definition: scene.py:749
def getCountObjects(self)
Definition: scene.py:746
def __init__(self, types=['ie', bb, te, tc)
Definition: scene.py:1728
def new(self, sIdx, camTypeIdx, session, sqlFields={})
Definition: scene.py:150
Declare virtual_loops object.
Definition: scene.py:1392
def new(self, camIdx, session, sqlFields={})
Definition: scene.py:233
def reverse(self)
Definition: scene.py:1412
def getHour(self)
Definition: scene.py:471
def __init__(self, objects)
Definition: scene.py:1579
Definition: filt.py:1
def __init__(self, offset=0)
Definition: scene.py:1369
def getImageSpaceFrameFilename(self, forceDistorted=False, allowNonExistant=False)
Definition: scene.py:448
def searchTreeForChildPosition(self, alignment, S, path=[])
Definition: scene.py:1232
def getResY(self)
Definition: scene.py:856
def __init__(self, spaceType='cameras', kwargs)
Definition: scene.py:1689
camera_matrix
Create and link abstract objects from data.
Definition: scene.py:843
camIds
Create and link abstract objects from data Camera stuff.
Definition: scene.py:661
def genRouteTree(self)
Definition: scene.py:1097
def getFullResultsFolder(self, analysis=None, customSubPath='')
Definition: scene.py:733
def exportToCode(self, moduleName='tvaMetaData')
Definition: scene.py:66
homography
Create and link abstract objects from data.
Definition: scene.py:223
def __getitem__(self, i)
Definition: scene.py:1406
def getUserTypeProbabilities(self)
Definition: scene.py:1333
def getHomography(self, type='undistorted')
Definition: scene.py:258
def getBaseDirectory(self)
Definition: scene.py:434
def __init__(self, spaceType='cameras', kwargs)
Definition: scene.py:1600
def getEndTime(self)
Definition: scene.py:476
def getSubSpacebyId(self, id)
Definition: scene.py:1652
def getSequenceCount(self)
Definition: scene.py:751
def getCoordCounts(self, i=[0, None, id=[0, None, m='hour')
Definition: scene.py:1475