comparison trafficintelligence/iframework.py @ 1172:f9ab0cbb92da

updates to iframework, to better reflect transport modes (suggestion)
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Tue, 12 Oct 2021 16:34:43 -0400
parents f1a33f458d7e
children c1766bb5076c
comparison
equal deleted inserted replaced
1171:afdbfba94fbc 1172:f9ab0cbb92da
1 ''' Framework to record data to measure the three street functions: access, transit and place '''
2
1 from enum import Enum 3 from enum import Enum
2 from pathlib import Path 4 from pathlib import Path
3 from datetime import datetime 5 from datetime import datetime
4 6
5 from sqlalchemy.ext.declarative import declarative_base, declared_attr 7 from sqlalchemy.ext.declarative import declarative_base, declared_attr
6 from sqlalchemy import Table, Column, Integer, Boolean, String, Float, DateTime, Enum as SQLEnum, ForeignKey, CheckConstraint, create_engine 8 from sqlalchemy import Table, Column, Integer, Boolean, String, Float, DateTime, Enum as SQLEnum, ForeignKey, CheckConstraint, create_engine
7 from sqlalchemy.orm import relationship, backref, sessionmaker 9 from sqlalchemy.orm import relationship, backref, sessionmaker
8 10
9 """
10
11 """
12
13 Base = declarative_base() 11 Base = declarative_base()
14 12
15 GenderEnum = Enum('GenderEnum', 'male female unknown') 13 GenderEnum = Enum('GenderEnum', 'male female unknown')
16 ModeEnum = Enum('ModeEnum', 'cardriver carpassenger transit bike walking scooter skating') 14 ModeEnum = Enum('ModeEnum', 'cardriver carpassenger transit taxi motorcycle cycling walking other') # the idea is that the mode could be sufficient to record all events (line and zone crossings), whether the actual, more precise vehicle, is
17 VehicleEnum = Enum('VehicleEnum', 'car SUV truck bus bike scooter skate rollers') 15 VehicleEnum = Enum('VehicleEnum', 'car suv van truck motorcycle bus bike scooter skate rollers')
18 16
19 # should there be a survey object for site info, observer, etc? 17 # should there be a survey object for site info, observer, etc?
20 18
21 class Mode(Base): 19 class Mode(Base):
22 'personal, because in a group (family), some might have a scooter or rollers' 20 '''A mode is personal, because in a group (family), some might have a scooter or rollers'''
23 __tablename__ = 'modes' 21 __tablename__ = 'modes'
24 idx = Column(Integer, primary_key=True) 22 idx = Column(Integer, primary_key=True)
25 personIdx = Column(Integer, ForeignKey('persons.idx')) 23 personIdx = Column(Integer, ForeignKey('persons.idx'))
26 vehicleIdx = Column(Integer, ForeignKey('vehicles.idx')) 24 vehicleIdx = Column(Integer, ForeignKey('vehicles.idx'))
27 transport = Column(SQLEnum(ModeEnum), nullable=False) 25 transport = Column(SQLEnum(ModeEnum), nullable=False)
28 startTime = Column(DateTime) # None first time if only one group 26 startTime = Column(DateTime) # None first time if only one mode
29 pointIdx = Column(Integer, ForeignKey('points.idx')) 27 pointIdx = Column(Integer, ForeignKey('points.idx'))
30 28
31 person = relationship('Person', backref = backref('modes')) 29 person = relationship('Person', backref = backref('modes'))
32 vehicle = relationship('Vehicle') 30 vehicle = relationship('Vehicle')
33 point = relationship('Point') 31 point = relationship('Point')
165 self.addPoint(x,y) 163 self.addPoint(x,y)
166 164
167 def addPoint(self, x, y): 165 def addPoint(self, x, y):
168 self.points.append(Point(x, y)) 166 self.points.append(Point(x, y))
169 167
170 class AbstractPassing: 168 class AbstractCrossing:
171 def initPersonGroupPassing(self, group, person, transport, vehicle): 169 def initPersonGroupCrossing(self, group, person, transport, vehicle):
172 ''' initiates with the passing the group or person 170 ''' initiates with the passing the group or person
173 171
174 design question: what should be done about simple line counting, 172 design question: what should be done about simple line counting,
175 without information about persons''' 173 without information about persons'''
176 if person is None and group is not None: # create group 174 if person is None and group is not None: # create group
182 if transport is not None: 180 if transport is not None:
183 Mode(transport, person, vehicle) 181 Mode(transport, person, vehicle)
184 else: 182 else:
185 print('Warning: passing person and group or both None') 183 print('Warning: passing person and group or both None')
186 184
187 class LinePassing(AbstractPassing,Base): 185 class LineCrossing(AbstractCrossing,Base):
188 __tablename__ = 'linepassings' 186 __tablename__ = 'linepassings'
189 idx = Column(Integer, primary_key=True) 187 idx = Column(Integer, primary_key=True)
190 lineIdx = Column(Integer, ForeignKey('lines.idx')) 188 lineIdx = Column(Integer, ForeignKey('lines.idx'))
191 groupIdx = Column(Integer, ForeignKey('groups.idx')) 189 groupIdx = Column(Integer, ForeignKey('groups.idx'))
192 pointIdx = Column(Integer, ForeignKey('points.idx')) 190 pointIdx = Column(Integer, ForeignKey('points.idx'))
204 self.line = line 202 self.line = line
205 self.instant = instant 203 self.instant = instant
206 self.speed = speed 204 self.speed = speed
207 self.wrongDirection = wrongDirection 205 self.wrongDirection = wrongDirection
208 self.point = p 206 self.point = p
209 self.initPersonGroupPassing(group, person, transport, vehicle) 207 self.initPersonGroupCrossing(group, person, transport, vehicle)
210 208
211 class ZoneCrossing(AbstractPassing,Base): 209 class ZoneCrossing(AbstractCrossing,Base):
212 __tablename__ = 'zonecrossings' 210 __tablename__ = 'zonecrossings'
213 idx = Column(Integer, primary_key=True) 211 idx = Column(Integer, primary_key=True)
214 zoneIdx = Column(Integer, ForeignKey('zones.idx')) 212 zoneIdx = Column(Integer, ForeignKey('zones.idx'))
215 groupIdx = Column(Integer, ForeignKey('groups.idx')) 213 groupIdx = Column(Integer, ForeignKey('groups.idx'))
216 pointIdx = Column(Integer, ForeignKey('points.idx')) 214 pointIdx = Column(Integer, ForeignKey('points.idx'))
224 def __init__(self, zone, instant, entering, p = None, group = None, person = None, transport = None, vehicle = None): 222 def __init__(self, zone, instant, entering, p = None, group = None, person = None, transport = None, vehicle = None):
225 self.zone = zone 223 self.zone = zone
226 self.instant = instant 224 self.instant = instant
227 self.entering = entering 225 self.entering = entering
228 self.point = p 226 self.point = p
229 self.initPersonGroupPassing(group, person, transport, vehicle) 227 self.initPersonGroupCrossing(group, person, transport, vehicle)
230 228
231 class Activity(AbstractPassing,Base): 229 class Activity(AbstractCrossing,Base):
232 __tablename__ = 'activities' 230 __tablename__ = 'activities'
233 idx = Column(Integer, primary_key=True) 231 idx = Column(Integer, primary_key=True)
234 activity = Column(String) # could be enum 232 activity = Column(String) # could be enum
235 groupIdx = Column(Integer, ForeignKey('groups.idx')) 233 groupIdx = Column(Integer, ForeignKey('groups.idx'))
236 # can an activity be done in a vehicle? Is it relevant? Can it be unambiguously identified? 234 # can an activity be done in a vehicle? Is it relevant? Can it be unambiguously identified?
247 self.activity = activity 245 self.activity = activity
248 self.startTime = startTime 246 self.startTime = startTime
249 self.endTime = endTime 247 self.endTime = endTime
250 self.zone = zone 248 self.zone = zone
251 self.point = p 249 self.point = p
252 self.initPersonGroupPassing(group, person, transport, vehicle) 250 self.initPersonGroupCrossing(group, person, transport, vehicle)
253 251
254 def createDatabase(filename): 252 def createDatabase(filename):
255 'creates a session to query the filename' 253 'creates a session to query the filename'
256 if Path(filename).is_file(): 254 if Path(filename).is_file():
257 print('The file '+filename+' exists') 255 print('The file '+filename+' exists')
282 modes = [Mode('cardriver', p, veh1), Mode('walking', p, startTime = datetime(2020,7,7,11,20))] 280 modes = [Mode('cardriver', p, veh1), Mode('walking', p, startTime = datetime(2020,7,7,11,20))]
283 281
284 line = Line('line1', 0.,0.,0.,10.) 282 line = Line('line1', 0.,0.,0.,10.)
285 zone = Zone('zone1', [0., 0., 1., 1.], [0., 1., 1., 0.]) 283 zone = Zone('zone1', [0., 0., 1., 1.], [0., 1., 1., 0.])
286 destination = Zone('destination1', [10., 10., 11., 11.], [10., 11., 11., 10.]) 284 destination = Zone('destination1', [10., 10., 11., 11.], [10., 11., 11., 10.])
287 counts = [LinePassing(line, datetime(2020,7,2,23,20+i), person = Person(20+i, 'female', disability = True), transport = 'walking') for i in range(5)] 285 counts = [LineCrossing(line, datetime(2020,7,2,23,20+i), person = Person(20+i, 'female', disability = True), transport = 'walking') for i in range(5)]
288 group1 = Group([Person(13+i,'female', False, False, True, False) for i in range(3)]) 286 group1 = Group([Person(13+i,'female', False, False, True, False) for i in range(3)])
289 groupMode1 = Mode.initGroup('walking', group1) 287 groupMode1 = Mode.initGroup('walking', group1)
290 activities = [Activity('walking', datetime(2020,7,2,23,0), datetime(2020,7,2,23,10), zone, person = Person(40, 'male', True, False, True, False)), 288 activities = [Activity('walking', datetime(2020,7,2,23,0), datetime(2020,7,2,23,10), zone, person = Person(40, 'male', True, False, True, False)),
291 Activity('eating', datetime(2020,7,2,23,10), datetime(2020,7,2,23,12), zone, person = Person(40, 'male', True, False, True, False)), 289 Activity('eating', datetime(2020,7,2,23,10), datetime(2020,7,2,23,12), zone, person = Person(40, 'male', True, False, True, False)),
292 Activity('playing', datetime(2020,7,2,22,0), datetime(2020,7,2,23,0), zone, group = group1)] 290 Activity('playing', datetime(2020,7,2,22,0), datetime(2020,7,2,23,0), zone, group = group1)]
293 counts.append(LinePassing(line, datetime(2020,7,2,23,5), group = group1)) 291 counts.append(LineCrossing(line, datetime(2020,7,2,23,5), group = group1))
294 counts.append(LinePassing(line, datetime(2020,7,2,23,7), person = Person(23, 'unknown'), transport = 'cardriver', vehicle = Vehicle('car'))) 292 counts.append(LineCrossing(line, datetime(2020,7,2,23,7), person = Person(23, 'unknown'), transport = 'cardriver', vehicle = Vehicle('car')))
295 counts.append(LinePassing(line, datetime(2020,7,2,23,9), person = Person('teen', 'unknown'), transport = 'scooter', vehicle = Vehicle('scooter'))) 293 counts.append(LineCrossing(line, datetime(2020,7,2,23,9), person = Person('teen', 'unknown'), transport = 'scooter', vehicle = Vehicle('scooter')))
296 counts.append(LinePassing(line, datetime(2020,7,2,23,11), person = Person(12, 'female'), transport = 'bike')) 294 counts.append(LineCrossing(line, datetime(2020,7,2,23,11), person = Person(12, 'female'), transport = 'bike'))
297 counts.append(LinePassing(line, datetime(2020,7,2,23,13), person = Person(), transport = 'cardriver')) # example of counting cars without knowing the driver and passenger's attributes 295 counts.append(LineCrossing(line, datetime(2020,7,2,23,13), person = Person(), transport = 'cardriver')) # example of counting cars without knowing the driver and passenger's attributes
298 counts.append(LinePassing(line, datetime(2020,7,2,23,15), group = Group([Person(34+i) for i in range(3)]), transport = 'carpassenger')) 296 counts.append(LineCrossing(line, datetime(2020,7,2,23,15), group = Group([Person(34+i) for i in range(3)]), transport = 'carpassenger'))
299 297
300 298
301 counts.append(ZoneCrossing(zone, datetime(2020,7,7,9,5), True, person = Person(33, 'male', False, False, True, False))) 299 counts.append(ZoneCrossing(zone, datetime(2020,7,7,9,5), True, person = Person(33, 'male', False, False, True, False)))
302 300
303 session.add_all([line, p, zone, group1, destination]+modes+groupMode1+counts+activities) 301 session.add_all([line, p, zone, group1, destination]+modes+groupMode1+counts+activities)