2626from datatypes .tour import Tour
2727from transform .impedance_transformer import ImpedanceTransformer
2828from models .linear import CarDensityModel
29+ from events .model_system_event_listener import EventHandler
2930import parameters .assignment as param
3031import parameters .zone as zone_param
3132import parameters .tour_generation as gen_param
@@ -58,7 +59,9 @@ def __init__(self,
5859 results_path : str ,
5960 assignment_model : AssignmentModel ,
6061 name : str ,
62+ event_handler : EventHandler ,
6163 estimation_data_path : Path = None ):
64+ self .event_handler = event_handler
6265 self .ass_model = cast (Union [MockAssignmentModel ,EmmeAssignmentModel ], assignment_model ) #type checker hint
6366 self .zone_numbers : numpy .array = self .ass_model .zone_numbers
6467 self .travel_modes : Dict [str , bool ] = {} # Dict instead of set, to preserve order
@@ -73,7 +76,8 @@ def __init__(self,
7376 if estimation_data_path :
7477 self .zdata_base .export_data (estimation_data_path / 'zonedata_base.csv' )
7578 self .zdata_forecast .export_data (estimation_data_path / 'zonedata_forecast.csv' )
76-
79+ self .event_handler .on_zone_data_loaded (self .zdata_base , self .zdata_forecast )
80+
7781 # Output data
7882 self .resultmatrices = MatrixData (
7983 os .path .join (results_path , name , "Matrices" ))
@@ -98,6 +102,7 @@ def __init__(self,
98102 self .convergence = []
99103 self .trucks = self .fm .calc_freight_traffic ("truck" )
100104 self .trailer_trucks = self .fm .calc_freight_traffic ("trailer_truck" )
105+ self .event_handler .on_model_system_initialized (self )
101106
102107 def _init_demand_model (self ):
103108 return DemandModel (self .zdata_forecast , self .resultdata , is_agent_model = False )
@@ -127,6 +132,7 @@ def _add_internal_demand(self, previous_iter_impedance, is_last_iteration, estim
127132 # as logsums from probability calculation are used in tour generation.
128133 self .dm .create_population_segments ()
129134 saved_pnr_impedance = {}
135+ self .event_handler .on_population_segments_created (self .dm )
130136 for purpose in self .dm .tour_purposes :
131137 if isinstance (purpose , SecDestPurpose ):
132138 purpose .gen_model .init_tours ()
@@ -143,6 +149,7 @@ def _add_internal_demand(self, previous_iter_impedance, is_last_iteration, estim
143149
144150 # Tour generation
145151 self .dm .generate_tours ()
152+ self .event_handler .on_demand_model_tours_generated (self .dm )
146153
147154 # Assigning of tours to mode, destination and time period
148155 for purpose in self .dm .tour_purposes :
@@ -172,6 +179,7 @@ def _add_internal_demand(self, previous_iter_impedance, is_last_iteration, estim
172179 break
173180 log .debug (f"Park and ride demand calculation completed." )
174181
182+ self .event_handler .on_purpose_demand_calculated (purpose , demand )
175183 if purpose .dest != "source" :
176184 for mode in demand :
177185 self .dtm .add_demand (demand [mode ])
@@ -249,9 +257,13 @@ def assign_base_demand(self,
249257 self ._calculate_noise_areas ()
250258 self .resultdata .flush ()
251259 self .dtm .init_demand ()
260+ self .event_handler .on_base_demand_assigned (impedance )
252261 return impedance
253262
254- def run_iteration (self , previous_iter_impedance , iteration = None , estimation_mode = False ):
263+ def run_iteration (self ,
264+ previous_iter_impedance : Dict [str , Dict [str , numpy .ndarray ]],
265+ iteration : Union [int , str ] = None ,
266+ estimation_mode = False ):
255267 """Calculate demand and assign to network.
256268
257269 Parameters
@@ -281,6 +293,7 @@ def run_iteration(self, previous_iter_impedance, iteration=None, estimation_mode
281293 value : numpy.ndarray
282294 Impedance (float 2-d matrix)
283295 """
296+ self .event_handler .on_iteration_started (iteration , previous_iter_impedance )
284297 impedance = {}
285298
286299 # Add truck and trailer truck demand, to time-period specific
@@ -292,9 +305,11 @@ def run_iteration(self, previous_iter_impedance, iteration=None, estimation_mode
292305 prediction = self .cdm .predict ()
293306 self .zdata_forecast ["car_density" ] = prediction
294307 self .zdata_forecast ["cars_per_1000" ] = 1000 * prediction
308+ self .event_handler .on_car_density_updated (iteration , prediction )
295309
296310 # Calculate internal demand
297311 self ._add_internal_demand (previous_iter_impedance , iteration == "last" , estimation_mode )
312+ self .event_handler .on_internal_demand_added (self .dtm )
298313
299314 # Calculate external demand
300315 for mode in param .external_modes :
@@ -310,8 +325,9 @@ def run_iteration(self, previous_iter_impedance, iteration=None, estimation_mode
310325 else :
311326 int_demand = self ._sum_trips_per_zone (mode )
312327 ext_demand = self .em .calc_external (mode , int_demand )
328+ self .event_handler .on_external_demand_calculated (ext_demand )
313329 self .dtm .add_demand (ext_demand )
314-
330+
315331 # Calculate tour sums and mode shares
316332 tour_sum = {mode : self ._sum_trips_per_zone (mode , include_dests = False )
317333 for mode in self .travel_modes }
@@ -343,11 +359,14 @@ def run_iteration(self, previous_iter_impedance, iteration=None, estimation_mode
343359 if iteration == "last" :
344360 self ._save_demand_to_omx (ap .name )
345361
362+ self .event_handler .on_demand_calculated (iteration , self .dtm )
363+
346364 # Calculate and return traffic impedance
347365 for ap in self .ass_model .assignment_periods :
348366 tp = ap .name
349367 log .info ("Assigning period " + tp )
350368 impedance [tp ] = ap .assign (self .dtm .demand [tp ], iteration )
369+ self .event_handler .on_time_period_assigned (iteration , ap , impedance [tp ])
351370 if tp == "aht" :
352371 self ._update_ratios (impedance [tp ], tp )
353372 if iteration == "last" : # TODO: Get uncongested time from assignment results
@@ -373,6 +392,7 @@ def run_iteration(self, previous_iter_impedance, iteration=None, estimation_mode
373392 self .convergence .append (gap )
374393 self .resultdata ._df_buffer ["demand_convergence.txt" ] = pandas .DataFrame (self .convergence )
375394 self .resultdata .flush ()
395+ self .event_handler .on_iteration_complete (iteration , impedance , gap )
376396 return impedance
377397
378398 def _save_demand_to_omx (self , tp ):
0 commit comments