Mercurial Hosting > traffic-intelligence
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) |