comparison trafficintelligence/iframework.py @ 1293:4dd446835e7d

update closer to Studio iframework
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Wed, 02 Oct 2024 12:19:12 -0400
parents c4c50678c856
children
comparison
equal deleted inserted replaced
1292:41219193baa0 1293:4dd446835e7d
9 from sqlalchemy.orm import relationship, backref, sessionmaker, declarative_base 9 from sqlalchemy.orm import relationship, backref, sessionmaker, declarative_base
10 10
11 Base = declarative_base() 11 Base = declarative_base()
12 12
13 GenderEnum = Enum('GenderEnum', 'male female unknown') 13 GenderEnum = Enum('GenderEnum', 'male female unknown')
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 14 ModeEnum = Enum('ModeEnum', 'car_driver car_passenger 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
15 VehicleEnum = Enum('VehicleEnum', 'car suv van truck motorcycle bus bike scooter skate rollers') 15 VehicleEnum = Enum('VehicleEnum', 'car bike van truck bus taxi motorcycle scooter skate rollers mobility_scooter')
16 ActivityEnum = Enum('ActivityEnum', 'unknown strolling jogging shopping sitting talking resting eating playing doing_exercise smoking using_cellphone observing reading_writing performing selling playing_with_pet taking_pet_for_walk')
17 DisabilityEnum = Enum('DisabilityEnum', 'none wheelchair walker cane white_cane')
18 AgeEnum = Enum('AgeEnum', 'unknown infant toddler child teen young_adult adult senior') # 0-1, 1-4, 4-12, 12-18...
16 19
17 # should there be a survey object for site info, observer, etc? 20 # should there be a survey object for site info, observer, etc?
18 21
19 class Mode(Base): 22 class Mode(Base):
20 '''A mode is personal, because in a group (family), some might have a scooter or rollers''' 23 '''A mode is personal, because in a group (family), some might have a scooter or rollers'''
72 # in aggregated form, there is a total number of observations for a given time interval, a number for each binary variable and k-1 variables for a categorical variable with k categories 75 # in aggregated form, there is a total number of observations for a given time interval, a number for each binary variable and k-1 variables for a categorical variable with k categories
73 class Person(Base): 76 class Person(Base):
74 __tablename__ = 'persons' 77 __tablename__ = 'persons'
75 idx = Column(Integer, primary_key=True) 78 idx = Column(Integer, primary_key=True)
76 #groupIdx = Column(Integer, ForeignKey('groups.idx')) 79 #groupIdx = Column(Integer, ForeignKey('groups.idx'))
77 age = Column(String) 80 age = Column(SQLEnum(AgeEnum), nullable=True) #Column(String)
78 gender = Column(SQLEnum(GenderEnum), nullable=False) 81 gender = Column(SQLEnum(GenderEnum), nullable=False)
79 disability = Column(String) # could be enum 82 disability = Column(String) #Column(SQLEnum(DisabilityEnum) #Boolean in Studio
80 stroller = Column(Boolean) # the booleans could be strings or enum to have more information 83 stroller = Column(Boolean) # the booleans could be strings or enum to have more information
81 bag = Column(Boolean) 84 bag = Column(Boolean)
82 animal = Column(Boolean) 85 animal = Column(Boolean)
86 # databaseFilename = Column(String) # refers to trajectory database, relative path
87 # objectIdx = Column(Integer) # refers to object id in trajectory database
83 88
84 #group = relationship('Group', backref = backref('persons')) 89 #group = relationship('Group', backref = backref('persons'))
85 90
86 def __init__(self, age = 'unknown', gender = 'unknown', disability = False, stroller = False, bag = False, animal = False): 91 def __init__(self, age = 'unknown', gender = 'unknown', disability = False, stroller = False, bag = False, animal = False):
87 self.age = age 92 self.age = age
98 try: 103 try:
99 return float(self.age) 104 return float(self.age)
100 except ValueError: 105 except ValueError:
101 pass 106 pass
102 else: 107 else:
103 return self.age 108 return self.age
104 109
105 def getGroups(self): 110 def getGroups(self):
106 if len(self.groupBelongings) > 0: 111 if len(self.groupBelongings) > 0:
107 return [gb.group for gb in self.groupBelongings] 112 return [gb.group for gb in self.groupBelongings]
108 else: 113 else:
109 return None 114 return None
110 115
111 class Vehicle(Base): 116 class Vehicle(Base):
112 __tablename__ = 'vehicles' 117 __tablename__ = 'vehicles'
113 idx = Column(Integer, primary_key=True) 118 idx = Column(Integer, primary_key=True)
114 category = Column(SQLEnum(VehicleEnum), nullable=False) 119 category = Column(SQLEnum(VehicleEnum), nullable=False)
115 trailer = Column(Boolean) 120 trailer = Column(Boolean)
121 # databaseFilename = Column(String) # refers to trajectory database, relative path
122 # objectIdx = Column(Integer) # refers to object id in trajectory database
116 123
117 def __init__(self, category, trailer = False): 124 def __init__(self, category, trailer = False):
118 self.category = category 125 self.category = category
119 self.trailer = trailer 126 self.trailer = trailer
120 127
129 self.y = y 136 self.y = y
130 137
131 pointLineAssociation = Table('pointlines', Base.metadata, 138 pointLineAssociation = Table('pointlines', Base.metadata,
132 Column('pointIdx', Integer, ForeignKey('points.idx')), 139 Column('pointIdx', Integer, ForeignKey('points.idx')),
133 Column('lineIdx', Integer, ForeignKey('lines.idx'))) 140 Column('lineIdx', Integer, ForeignKey('lines.idx')))
134 141
135 class Line(Base): 142 class Line(Base):
136 __tablename__ = 'lines' 143 __tablename__ = 'lines'
137 idx = Column(Integer, primary_key=True) 144 idx = Column(Integer, primary_key=True)
138 name = Column(String) 145 name = Column(String)
139 # todo define lines for access counting: add type? - AccessLine? 146 # todo define lines for access counting: add type? - AccessLine?
157 164
158 def __init__(self, name, xs = None, ys = None): 165 def __init__(self, name, xs = None, ys = None):
159 'xs and ys are the list of x and y coordinates' 166 'xs and ys are the list of x and y coordinates'
160 self.name = name 167 self.name = name
161 if xs is not None and ys is not None: 168 if xs is not None and ys is not None:
162 for x,y in zip(xs, ys): 169 for x, y in zip(xs, ys):
163 self.addPoint(x,y) 170 self.addPoint(x, y)
164 171
165 def addPoint(self, x, y): 172 def addPoint(self, x, y):
166 self.points.append(Point(x, y)) 173 self.points.append(Point(x, y))
167 174
168 class AbstractCrossing: 175 class AbstractCrossing:
169 def initPersonGroupCrossing(self, group, person, modeName, vehicle): 176 def initPersonGroupCrossing(self, group, person, modeName, vehicle):
188 lineIdx = Column(Integer, ForeignKey('lines.idx')) 195 lineIdx = Column(Integer, ForeignKey('lines.idx'))
189 groupIdx = Column(Integer, ForeignKey('groups.idx')) 196 groupIdx = Column(Integer, ForeignKey('groups.idx'))
190 pointIdx = Column(Integer, ForeignKey('points.idx')) 197 pointIdx = Column(Integer, ForeignKey('points.idx'))
191 instant = Column(DateTime) 198 instant = Column(DateTime)
192 speed = Column(Float) 199 speed = Column(Float)
193 wrongDirection = Column(Boolean) 200 # wrongDirection = Column(Boolean)
201 rightToLeft = Column(Boolean)
194 202
195 line = relationship('Line') 203 line = relationship('Line')
196 group = relationship('Group') 204 group = relationship('Group')
197 point = relationship('Point') 205 point = relationship('Point')
198 206
212 zoneIdx = Column(Integer, ForeignKey('zones.idx')) 220 zoneIdx = Column(Integer, ForeignKey('zones.idx'))
213 groupIdx = Column(Integer, ForeignKey('groups.idx')) 221 groupIdx = Column(Integer, ForeignKey('groups.idx'))
214 pointIdx = Column(Integer, ForeignKey('points.idx')) 222 pointIdx = Column(Integer, ForeignKey('points.idx'))
215 instant = Column(DateTime) 223 instant = Column(DateTime)
216 entering = Column(Boolean) 224 entering = Column(Boolean)
225 speed = Column(Float)
217 226
218 zone = relationship('Zone') 227 zone = relationship('Zone')
219 group = relationship('Group') 228 group = relationship('Group')
220 point = relationship('Point') 229 point = relationship('Point')
221 230
222 def __init__(self, zone, instant, entering, p = None, group = None, person = None, modeName = None, vehicle = None): 231 def __init__(self, zone, instant, entering, speed = None, p = None, group = None, person = None, modeName = None, vehicle = None):
223 self.zone = zone 232 self.zone = zone
224 self.instant = instant 233 self.instant = instant
225 self.entering = entering 234 self.entering = entering
235 self.speed = speed
226 self.point = p 236 self.point = p
227 self.initPersonGroupCrossing(group, person, modeName, vehicle) 237 self.initPersonGroupCrossing(group, person, modeName, vehicle)
228 238
229 class Activity(AbstractCrossing,Base): 239 class Activity(AbstractCrossing,Base):
230 __tablename__ = 'activities' 240 __tablename__ = 'activities'
231 idx = Column(Integer, primary_key=True) 241 idx = Column(Integer, primary_key=True)
232 activity = Column(String) # could be enum 242 activity = Column(SQLEnum(ActivityEnum), nullable=False) #Column(String)
233 groupIdx = Column(Integer, ForeignKey('groups.idx')) 243 groupIdx = Column(Integer, ForeignKey('groups.idx'))
234 # can an activity be done in a vehicle? Is it relevant? Can it be unambiguously identified? 244 # can an activity be done in a vehicle? Is it relevant? Can it be unambiguously identified?
235 startTime = Column(DateTime) 245 startTime = Column(DateTime)
236 endTime = Column(DateTime) 246 endTime = Column(DateTime)
237 zoneIdx = Column(Integer, ForeignKey('zones.idx')) 247 zoneIdx = Column(Integer, ForeignKey('zones.idx'))
238 pointIdx = Column(Integer, ForeignKey('points.idx')) 248 pointIdx = Column(Integer, ForeignKey('points.idx'))
239 249
240 group = relationship('Group') 250 group = relationship('Group')
241 zone = relationship('Zone') 251 zone = relationship('Zone')
242 point = relationship('Point') 252 point = relationship('Point')
243 253
244 def __init__(self, activity, startTime, endTime, zone, p = None, group = None, person = None, modeName = None, vehicle = None): 254 def __init__(self, activity, startTime, endTime, zone, p = None, group = None, person = None, modeName = None, vehicle = None):
254 if Path(filename).is_file() and not insertInExisting: 264 if Path(filename).is_file() and not insertInExisting:
255 print('The file '+filename+' exists') 265 print('The file '+filename+' exists')
256 return None 266 return None
257 else: 267 else:
258 engine = create_engine('sqlite:///'+filename) 268 engine = create_engine('sqlite:///'+filename)
259 if createOnlyGroupTables: 269 if createOnlyGroupTables:
260 Base.metadata.create_all(engine, tables = [Base.metadata.tables['modes'], Base.metadata.tables['groups'], Base.metadata.tables['groupbelongings'], Base.metadata.tables['persons'], Base.metadata.tables['vehicles'], Base.metadata.tables['points']]) 270 Base.metadata.create_all(engine, tables = [Base.metadata.tables['modes'], Base.metadata.tables['groups'], Base.metadata.tables['groupbelongings'], Base.metadata.tables['persons'], Base.metadata.tables['vehicles'], Base.metadata.tables['points']])
261 else: 271 else:
262 Base.metadata.create_all(engine) 272 Base.metadata.create_all(engine)
263 Session = sessionmaker(bind=engine) 273 Session = sessionmaker(bind=engine)
264 return Session() 274 return Session()
276 if __name__ == '__main__': # demo code 286 if __name__ == '__main__': # demo code
277 session = createDatabase('test.sqlite') 287 session = createDatabase('test.sqlite')
278 if session is None: 288 if session is None:
279 session = connectDatabase('test.sqlite') 289 session = connectDatabase('test.sqlite')
280 # count example 290 # count example
281 p = Person(6, 'female', bag = True) 291 p = Person('infant', 'female', bag = True)
282 veh1 = Vehicle('car') 292 veh1 = Vehicle('car')
283 modes = [Mode('cardriver', p, veh1), Mode('walking', p, startTime = datetime(2020,7,7,11,20))] 293 modes = [Mode('cardriver', p, veh1), Mode('walking', p, startTime = datetime(2020,7,7,11,20))]
284 294
285 line = Line('line1', 0.,0.,0.,10.) 295 line = Line('line1', 0.,0.,0.,10.)
286 zone = Zone('zone1', [0., 0., 1., 1.], [0., 1., 1., 0.]) 296 zone = Zone('zone1', [0., 0., 1., 1.], [0., 1., 1., 0.])
287 destination = Zone('destination1', [10., 10., 11., 11.], [10., 11., 11., 10.]) 297 destination = Zone('destination1', [10., 10., 11., 11.], [10., 11., 11., 10.])
288 counts = [LineCrossing(line, datetime(2020,7,2,23,20+i), person = Person(20+i, 'female', disability = True), modeName = 'walking') for i in range(5)] 298 counts = [LineCrossing(line, datetime(2020,7,2,23,20+i), person = Person(AgeEnum(1+i), 'female', disability = True), modeName = 'walking') for i in range(5)]
289 group1 = Group([Person(13+i,'female', False, False, True, False) for i in range(3)]) 299 group1 = Group([Person(AgeEnum(3+i),'female', False, False, True, False) for i in range(3)])
290 groupMode1 = Mode.initGroup('walking', group1) 300 groupMode1 = Mode.initGroup('walking', group1)
291 activities = [Activity('walking', datetime(2020,7,2,23,0), datetime(2020,7,2,23,10), zone, person = Person(40, 'male', True, False, True, False)), 301 activities = [Activity('strolling', datetime(2020,7,2,23,0), datetime(2020,7,2,23,10), zone, person = Person('adult', 'male', True, False, True, False)),
292 Activity('eating', datetime(2020,7,2,23,10), datetime(2020,7,2,23,12), zone, person = Person(40, 'male', True, False, True, False)), 302 Activity('eating', datetime(2020,7,2,23,10), datetime(2020,7,2,23,12), zone, person = Person('senior', 'male', True, False, True, False)),
293 Activity('playing', datetime(2020,7,2,22,0), datetime(2020,7,2,23,0), zone, group = group1)] 303 Activity('playing', datetime(2020,7,2,22,0), datetime(2020,7,2,23,0), zone, group = group1)]
294 counts.append(LineCrossing(line, datetime(2020,7,2,23,5), group = group1)) 304 counts.append(LineCrossing(line, datetime(2020,7,2,23,5), group = group1))
295 counts.append(LineCrossing(line, datetime(2020,7,2,23,7), person = Person(23, 'unknown'), modeName = 'cardriver', vehicle = Vehicle('car'))) 305 counts.append(LineCrossing(line, datetime(2020,7,2,23,7), person = Person('young_adult', 'unknown'), modeName = 'cardriver', vehicle = Vehicle('car')))
296 counts.append(LineCrossing(line, datetime(2020,7,2,23,9), person = Person('teen', 'unknown'), modeName = 'other', vehicle = Vehicle('scooter'))) 306 counts.append(LineCrossing(line, datetime(2020,7,2,23,9), person = Person('teen', 'unknown'), modeName = 'other', vehicle = Vehicle('scooter')))
297 counts.append(LineCrossing(line, datetime(2020,7,2,23,11), person = Person(12, 'female'), modeName = 'cycling')) 307 counts.append(LineCrossing(line, datetime(2020,7,2,23,11), person = Person('teen', 'female'), modeName = 'cycling'))
298 counts.append(LineCrossing(line, datetime(2020,7,2,23,13), person = Person(), modeName = 'cardriver')) # example of counting cars without knowing the driver and passenger's attributes 308 counts.append(LineCrossing(line, datetime(2020,7,2,23,13), person = Person(), modeName = 'cardriver')) # example of counting cars without knowing the driver and passenger's attributes
299 counts.append(LineCrossing(line, datetime(2020,7,2,23,15), group = Group([Person(34+i) for i in range(3)]), modeName = 'carpassenger')) 309 counts.append(LineCrossing(line, datetime(2020,7,2,23,15), group = Group([Person(AgeEnum(6+i)) for i in range(3)]), modeName = 'car_passenger'))
300 310
301 311 counts.append(ZoneCrossing(zone, datetime(2020,7,7,9,5), True, person = Person('adult', 'male', False, False, True, False)))
302 counts.append(ZoneCrossing(zone, datetime(2020,7,7,9,5), True, person = Person(33, 'male', False, False, True, False)))
303 312
304 session.add_all([line, p, zone, group1, destination]+modes+groupMode1+counts+activities) 313 session.add_all([line, p, zone, group1, destination]+modes+groupMode1+counts+activities)
305 314
306 session.commit() 315 session.commit()
307 session.close() 316 session.close()