1# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo 2# Copyright (C) 2016-2019 German Aerospace Center (DLR) and others. 3# SUMOPy module 4# Copyright (C) 2012-2017 University of Bologna - DICAM 5# This program and the accompanying materials 6# are made available under the terms of the Eclipse Public License v2.0 7# which accompanies this distribution, and is available at 8# http://www.eclipse.org/legal/epl-v20.html 9# SPDX-License-Identifier: EPL-2.0 10 11# @file origin_to_destination.py 12# @author Joerg Schweizer 13# @date 14# @version $Id$ 15 16 17import numpy as np 18from numpy import random 19import agilepy.lib_base.classman as cm 20import agilepy.lib_base.arrayman as am 21import agilepy.lib_base.xmlman as xm 22#from coremodules.modules_common import * 23from coremodules.network.network import SumoIdsConf, MODES 24from coremodules.network import routing 25from agilepy.lib_base.processes import Process, CmlMixin 26#import coremodules.demand.demand as dm 27import demand as dm 28import demandbase as db 29# print 'dir(dm)',dir(dm) 30#from demand import OPTIONMAP_POS_DEPARTURE 31# OPTIONMAP_POS_ARRIVAL 32# OPTIONMAP_SPEED_DEPARTURE 33# OPTIONMAP_SPEED_ARRIVAL 34# OPTIONMAP_LANE_DEPART 35# OPTIONMAP_LANE_ARRIVAL 36 37 38class OdTripgenerator(Process): 39 def __init__(self, odintervals, trips, logger=None, **kwargs): 40 """ 41 CURRENTLY NOT IN USE!! 42 """ 43 self._init_common('odtripgenerator', name='OD tripgenerator', 44 logger=logger, 45 info='Generates trips from OD demand .', 46 ) 47 self._odintervals = odintervals 48 49 attrsman = self.get_attrsman() 50 self.add_option('netfilepath', netfilepath, 51 # this will make it show up in the dialog 52 groupnames=['options'], 53 cml='--sumo-net-file', 54 perm='rw', 55 name='Net file', 56 wildcards='Net XML files (*.net.xml)|*.net.xml', 57 metatype='filepath', 58 info='SUMO Net file in XML format.', 59 ) 60 61 self.workdirpath = attrsman.add(cm.AttrConf('workdirpath', rootdirpath, 62 # ['options'],#['_private'], 63 groupnames=['_private'], 64 perm='r', 65 name='Workdir', 66 metatype='dirpath', 67 info='Working directory for this scenario.', 68 )) 69 70 self.rootname = attrsman.add(cm.AttrConf('rootname', rootname, 71 groupnames=['_private'], 72 perm='r', 73 name='Scenario shortname', 74 info='Scenario shortname is also rootname of converted files.', 75 )) 76 77 self.is_clean_nodes = attrsman.add(cm.AttrConf('is_clean_nodes', is_clean_nodes, 78 groupnames=['options'], 79 perm='rw', 80 name='Clean Nodes', 81 info='If set, then shapes around nodes are cleaned up.', 82 )) 83 84 def update_params(self): 85 """ 86 Make all parameters consistent. 87 example: used by import OSM to calculate/update number of tiles 88 from process dialog 89 """ 90 pass 91 #self.workdirpath = os.path.dirname(self.netfilepath) 92 #bn = os.path.basename(self.netfilepath).split('.') 93 # if len(bn)>0: 94 # self.rootname = bn[0] 95 96 def do(self): 97 self.update_params() 98 cml = self.get_cml()+' --plain-output-prefix ' + \ 99 filepathlist_to_filepathstring( 100 os.path.join(self.workdirpath, self.rootname)) 101 # print 'SumonetImporter.do',cml 102 #import_xml(self, rootname, dirname, is_clean_nodes = True) 103 self.run_cml(cml) 104 if self.status == 'success': 105 self._net.import_xml( 106 self.rootname, self.workdirpath, is_clean_nodes=self.is_clean_nodes) 107 return True 108 else: 109 return False 110 # print 'do',self.newident 111 # self._scenario = Scenario( self.newident, 112 # parent = None, 113 # workdirpath = self.workdirpath, 114 # logger = self.get_logger(), 115 # ) 116 117 def get_net(self): 118 return self._net 119 120 121class OdFlowTable(am.ArrayObjman): 122 def __init__(self, parent, modes, zones, activitytypes=None, **kwargs): 123 self._init_objman(ident='odflowtab', parent=parent, 124 name='OD flows', 125 info='Table with intervals, modes, OD and respective number of trips.', 126 #xmltag = ('odtrips','odtrip',None), 127 **kwargs) 128 129 self.add_col(am.ArrayConf('times_start', 0, 130 groupnames=['parameters'], 131 perm='r', 132 name='Start time', 133 unit='s', 134 info='Start time of interval in seconds (no fractional seconds).', 135 xmltag='t_start', 136 )) 137 138 self.add_col(am.ArrayConf('times_end', 3600, 139 groupnames=['parameters'], 140 perm='r', 141 name='End time', 142 unit='s', 143 info='End time of interval in seconds (no fractional seconds).', 144 xmltag='t_end', 145 )) 146 147 self.add_col(am.IdsArrayConf('ids_mode', modes, 148 groupnames=['parameters'], 149 perm='r', 150 #choices = MODES, 151 name='ID mode', 152 xmltag='vClass', 153 info='ID of transport mode.', 154 )) 155 156 self.add_col(am.IdsArrayConf('ids_orig', zones, 157 groupnames=['parameters'], 158 name='Orig.', 159 perm='r', 160 #choices = zones.ids_sumo.get_indexmap(), 161 info='traffic assignment zone of origin of trip.', 162 xmltag='id_orig', 163 )) 164 165 self.add_col(am.IdsArrayConf('ids_dest', zones, 166 groupnames=['parameters'], 167 name='Dest.', 168 perm='r', 169 #choices = zones.ids_sumo.get_indexmap(), 170 info='ID of traffic assignment zone of destination of trip.', 171 xmltag='id_dest', 172 )) 173 174 self.add_col(am.ArrayConf('tripnumbers', 0, 175 groupnames=['state'], 176 perm='rw', 177 name='Trips', 178 info='Number of trips from zone with ID Orig to zone with ID Dest.', 179 xmltag='tripnumber', 180 )) 181 182 if activitytypes is not None: 183 self.add_col(am.IdsArrayConf('ids_activitytype_orig', activitytypes, 184 groupnames=['parameters'], 185 perm='rw', 186 #choices = activitytypes.names.get_indexmap(), 187 name='Activity type at orig.', 188 symbol='Act. orig.', 189 info='Type of activity performed at origin, before the trip.', 190 )) 191 192 self.add_col(am.IdsArrayConf('ids_activitytype_dest', activitytypes, 193 groupnames=['parameters'], 194 perm='rw', 195 #choices = activitytypes.names.get_indexmap(), 196 name='Activity type at dest.', 197 symbol='Act. dest.', 198 info='Type of activity performed at destination, after the trip.', 199 )) 200 #self.add( cm.ObjConf( zones, is_child = False,groups = ['_private'])) 201 202 def add_flows(self, time_start, 203 time_end, 204 id_mode, 205 ids_orig, 206 ids_dest, 207 tripnumbers, 208 id_activitytype_orig=1, 209 id_activitytype_dest=1, 210 ): 211 n = len(tripnumbers) 212 self.add_rows(n=n, 213 times_start=time_start*np.ones(n), 214 times_end=time_end*np.ones(n), 215 ids_mode=id_mode*np.ones(n), 216 ids_orig=ids_orig, 217 ids_dest=ids_dest, 218 tripnumbers=tripnumbers, 219 ids_activitytype_orig=id_activitytype_orig*np.ones(n), 220 ids_activitytype_dest=id_activitytype_dest*np.ones(n), 221 ) 222 223 224class OdTrips(am.ArrayObjman): 225 def __init__(self, ident, parent, zones, **kwargs): 226 self._init_objman(ident, parent=parent, 227 name='OD trips', 228 info='Contains the number of trips between an origin and a destination zone.', 229 version=0.2, 230 xmltag=('odtrips', 'odtrip', None), **kwargs) 231 232 self._init_attributes(zones) 233 234 def _init_attributes(self, zones=None): 235 # print '_init_attributes',self.ident 236 if not self.has_attrname('zones'): 237 self.add(cm.ObjConf( 238 zones, is_child=False, groups=['_private'])) 239 else: 240 # zones is already an attribute 241 zones = self.zones.get_value() 242 243 if self.get_version() < 0.1: 244 # update attrs from previous 245 # IdsArrayConf not yet modifiable interactively, despite perm = 'rw',!!! 246 self.ids_orig.set_perm('rw') 247 self.ids_dest.set_perm('rw') 248 249 if hasattr(self, 'func_delete_row'): 250 self.func_make_row._is_returnval = False 251 self.func_delete_row._is_returnval = False 252 253 self.add_col(am.IdsArrayConf('ids_orig', zones, 254 groupnames=['state'], 255 perm='rw', 256 name='Orig.', 257 #choices = zones.ids_sumo.get_indexmap(), 258 info='traffic assignment zone of origin of trip.', 259 xmltag='id_orig', 260 )) 261 262 self.add_col(am.IdsArrayConf('ids_dest', zones, 263 groupnames=['state'], 264 perm='rw', 265 name='Dest.', 266 #choices = zones.ids_sumo.get_indexmap(), 267 info='ID of traffic assignment zone of destination of trip.', 268 xmltag='id_dest', 269 )) 270 271 self.add_col(am.ArrayConf('tripnumbers', 0, 272 groupnames=['state'], 273 perm='rw', 274 name='Trips', 275 info='Number of trips from zone with ID Orig to zone with ID Dest.', 276 xmltag='tripnumber', 277 )) 278 279 # print ' pre add func_make_row' 280 self.add(cm.FuncConf('func_make_row', 'on_add_row', None, 281 groupnames=['rowfunctions', '_private'], 282 name='New OD flow.', 283 info='Add a new OD flow.', 284 is_returnval=False, 285 )) 286 # print ' post add func_make_row' 287 self.add(cm.FuncConf('func_delete_row', 'on_del_row', None, 288 groupnames=['rowfunctions', '_private'], 289 name='Del OD flow', 290 info='Delete OD flow.', 291 is_returnval=False, 292 )) 293 294 # print ' _init_attributes done',self.ident 295 296 def _init_constants(self): 297 #self.edgeweights_orig = None 298 #self.edgeweights_dest = None 299 pass 300 301 def on_del_row(self, id_row=None): 302 if id_row is not None: 303 # print 'on_del_row', id_row 304 self.del_row(id_row) 305 306 def on_add_row(self, id_row=None): 307 print 'on_add_row' 308 if len(self) > 0: 309 310 # copy previous 311 od_last = self.get_row(self.get_ids()[-1]) 312 #id_orig = self.odtab.ids_orig.get(id_last) 313 #id_dest = self.odtab.ids_dest.get(id_last) 314 #id = self.suggest_id() 315 self.add_row(**od_last) 316 else: 317 self.add_row(self.suggest_id()) 318 319 def generate_odflows(self, odflowtab, time_start, time_end, id_mode, **kwargs): 320 """ 321 Insert all od flows in odflowtab. 322 """ 323 # for id_od in self.get_ids(): 324 odflowtab.add_flows(time_start, 325 time_end, 326 id_mode, 327 self.ids_orig.get_value(), 328 self.ids_dest.get_value(), 329 self.tripnumbers.get_value(), 330 **kwargs 331 ) 332 333 def generate_trips(self, demand, time_start, time_end, id_mode, 334 pos_depart_default=db.OPTIONMAP_POS_DEPARTURE['random_free'], 335 #pos_arrival_default = db.OPTIONMAP_POS_ARRIVAL['max'], 336 pos_arrival_default=db.OPTIONMAP_POS_ARRIVAL['random'], 337 speed_depart_default=0.0, 338 speed_arrival_default=0.0, 339 # pedestrians always depart on lane 0 340 ind_lane_depart_default=db.OPTIONMAP_LANE_DEPART['allowed'], 341 # pedestrians always arrive on lane 0 342 ind_lane_arrival_default=db.OPTIONMAP_LANE_ARRIVAL['current'], 343 n_trials_connect=5, 344 is_make_route=True, 345 ): 346 """ 347 Generates trips in demand.trip table. 348 """ 349 print 'generate_trips', time_start, time_end, id_mode 350 id_mode_ped = MODES['pedestrian'] 351 #OPTIONMAP_POS_DEPARTURE = { -1:"random",-2:"free",-3:"random_free",-4:"base"} 352 #OPTIONMAP_POS_ARRIVAL = { -1:"random",-2:"max"} 353 #OPTIONMAP_SPEED_DEPARTURE = { -1:"random",-2:"max"} 354 #OPTIONMAP_SPEED_ARRIVAL = { -1:"current"} 355 #OPTIONMAP_LANE_DEPART = {-1:"random",-2:"free",-3:"departlane"} 356 #OPTIONMAP_LANE_ARRIVAL = { -1:"current"} 357 358 trips = demand.trips 359 #ids_vtype_mode = demand.vtypes.select_by_mode(id_mode) 360 ids_vtype_mode, prob_vtype_mode = demand.vtypes.select_by_mode( 361 id_mode, is_share=True) 362 # print ' ids_vtype_mode', ids_vtype_mode 363 n_vtypes = len(ids_vtype_mode) 364 zones = self.zones.get_value() 365 edges = zones.ids_edges_orig.get_linktab() 366 edgelengths = edges.lengths 367 368 if n_trials_connect > 0: 369 # initialize routing to verify connection 370 fstar = edges.get_fstar(is_ignor_connections=False) 371 times = edges.get_times(id_mode=id_mode, is_check_lanes=True) 372 373 n_trips_generated = 0 374 n_trips_failed = 0 375 376 is_nocon = False 377 route = [] 378 for id_od in self.get_ids(): 379 id_orig = self.ids_orig[id_od] 380 id_dest = self.ids_dest[id_od] 381 tripnumber = self.tripnumbers[id_od] 382 383 ids_edges_orig_raw = zones.ids_edges_orig[id_orig] 384 ids_edges_dest_raw = zones.ids_edges_dest[id_dest] 385 386 prob_edges_orig_raw = zones.probs_edges_orig[id_orig] 387 prob_edges_dest_raw = zones.probs_edges_dest[id_dest] 388 389 # check accessibility of origin edges 390 ids_edges_orig = [] 391 prob_edges_orig = [] 392 inds_lane_orig = [] 393 for i in xrange(len(ids_edges_orig_raw)): 394 id_edge = ids_edges_orig_raw[i] 395 # if check accessibility... 396 ind_lane_depart = edges.get_laneindex_allowed(id_edge, id_mode) 397 # print ' get_laneindex_allowed',id_mode,id_edge,edges.ids_sumo[id_edge],ind_lane_depart 398 if ind_lane_depart >= 0: 399 ids_edges_orig.append(id_edge) 400 prob_edges_orig.append(prob_edges_orig_raw[i]) 401 inds_lane_orig.append(ind_lane_depart) 402 403 # check accessibility of destination edges 404 ids_edges_dest = [] 405 prob_edges_dest = [] 406 inds_lane_dest = [] 407 for i in xrange(len(ids_edges_dest_raw)): 408 id_edge = ids_edges_dest_raw[i] 409 # if check accessibility... 410 ind_lane_arrival = edges.get_laneindex_allowed( 411 id_edge, id_mode) 412 if ind_lane_arrival >= 0: 413 ids_edges_dest.append(id_edge) 414 prob_edges_dest.append(prob_edges_dest_raw[i]) 415 inds_lane_dest.append(ind_lane_arrival) 416 417 n_edges_orig = len(ids_edges_orig) 418 n_edges_dest = len(ids_edges_dest) 419 420 if (n_edges_orig > 0) & (n_edges_dest > 0) & (tripnumber > 0): 421 # renormalize weights 422 prob_edges_orig = np.array(prob_edges_orig, np.float) 423 prob_edges_orig = prob_edges_orig/np.sum(prob_edges_orig) 424 prob_edges_dest = np.array(prob_edges_dest, np.float) 425 prob_edges_dest = prob_edges_dest/np.sum(prob_edges_dest) 426 427 for d in xrange(int(tripnumber+0.5)): 428 time_depart = random.uniform(time_start, time_end) 429 430 if (n_trials_connect > 0) & (id_mode != id_mode_ped): 431 # check if origin and destination edges are connected 432 n = n_trials_connect 433 is_nocon = True 434 while (n > 0) & is_nocon: 435 # this algorithm can be improved by calculating 436 # the minimum cost tree and chacking all destinations 437 i_orig = np.argmax(random.rand( 438 n_edges_orig)*prob_edges_orig) 439 id_edge_orig = ids_edges_orig[i_orig] 440 i_dest = np.argmax(random.rand( 441 n_edges_dest)*prob_edges_dest) 442 id_edge_dest = ids_edges_dest[i_dest] 443 444 cost, route = routing.get_mincostroute_edge2edge(id_edge_orig, 445 id_edge_dest, 446 weights=times, 447 fstar=fstar 448 ) 449 is_nocon = len(route) == 0 450 n -= 1 451 # print ' found route',len(route),n_trials_connect-n 452 if not is_make_route: 453 route = [] 454 else: 455 # no check if origin and destination edges are connected 456 i_orig = np.argmax(random.rand( 457 n_edges_orig)*prob_edges_orig) 458 id_edge_orig = ids_edges_orig[i_orig] 459 460 i_dest = np.argmax(random.rand( 461 n_edges_dest)*prob_edges_dest) 462 id_edge_dest = ids_edges_dest[i_dest] 463 464 if not is_nocon: 465 ind_lane_orig = inds_lane_orig[i_orig] 466 ind_lane_dest = inds_lane_dest[i_dest] 467 468 pos_depart = pos_depart_default 469 pos_arrival = pos_arrival_default 470 # print ' bef:pos_depart,pos_arrival,id_mode,id_mode_ped', pos_depart,pos_arrival,id_mode,id_mode_ped 471 if id_mode_ped == id_mode: 472 # persons do not understand "random", "max" etc 473 # so produce a random number here 474 475 #{ -1:"random",-2:"free",-3:"random_free",-4:"base"} 476 edgelength = edgelengths[id_edge_orig] 477 if pos_depart in (-1, -2, -3): 478 pos_depart = random.uniform( 479 0.1*edgelength, 0.9*edgelength, 1)[0] 480 else: 481 pos_depart = 0.1*edgelength 482 483 # { -1:"random",-2:"max"} 484 edgelength = edgelengths[id_edge_dest] 485 if pos_arrival == -1: 486 pos_arrival = random.uniform( 487 0.1*edgelength, 0.9*edgelength, 1)[0] 488 else: 489 pos_arrival = 0.9*edgelength 490 # print ' af:pos_depart,pos_arrival,id_mode,id_mode_ped', pos_depart,pos_arrival,id_mode,id_mode_ped 491 # print ' n_vtypes',n_vtypes 492 # print ' random.randint(n_vtypes)',random.randint(n_vtypes) 493 #id_vtype = ids_vtype_mode[random.randint(n_vtypes)] 494 id_vtype = ids_vtype_mode[np.argmax( 495 random.rand(n_vtypes)*prob_vtype_mode)] 496 id_trip = trips.make_trip(id_vtype=id_vtype, 497 time_depart=time_depart, 498 id_edge_depart=id_edge_orig, 499 id_edge_arrival=id_edge_dest, 500 ind_lane_depart=ind_lane_orig, 501 ind_lane_arrival=ind_lane_dest, 502 position_depart=pos_depart, 503 position_arrival=pos_arrival, 504 speed_depart=speed_depart_default, 505 speed_arrival=speed_arrival_default, 506 route=route, 507 ) 508 # print ' ',id_trip,id_edge_orig,edges.ids_sumo[id_edge_orig],ind_lane_depart 509 # print ' ',id_trip,self.position_depart[id_trip], 510 n_trips_generated += 1 511 else: 512 n_trips_failed += tripnumber 513 else: 514 n_trips_failed += tripnumber 515 516 print ' n_trips_generated', n_trips_generated 517 print ' n_trips_failed', n_trips_failed 518 519 def add_od_trips(self, scale, names_orig, names_dest, tripnumbers): 520 print 'OdTrips.add_od_trips' 521 # print ' scale, names_orig, names_dest, tripnumbers',scale, names_orig, names_dest, tripnumbers,len(tripnumbers) 522 zones = self.get_zones() 523 524 for name_orig, name_dest, tripnumber in zip(names_orig, names_dest, tripnumbers): 525 # print ' check',name_orig, name_dest, tripnumbers,zones.ids_sumo.has_index(name_orig),zones.ids_sumo.has_index(name_dest) 526 if (zones.ids_sumo.has_index(name_orig)) & (zones.ids_sumo.has_index(name_dest)): 527 print ' add', zones.ids_sumo.get_id_from_index( 528 name_orig), zones.ids_sumo.get_id_from_index(name_dest) 529 self.add_row(ids_orig=zones.ids_sumo.get_id_from_index(name_orig), 530 ids_dest=zones.ids_sumo.get_id_from_index( 531 name_dest), 532 tripnumbers=scale * tripnumber) 533 else: 534 print ' WARNING: zone named %s or %s not known' % ( 535 name_orig, names_dest) 536 print ' zones indexmap', zones.get_indexmap() 537 print ' ids_sumo', zones.ids_sumo.get_value() 538 print ' ids_sumo._index_to_id', zones.ids_sumo._index_to_id 539 540 def get_zones(self): 541 return self.ids_dest.get_linktab() 542 543 544class OdModes(am.ArrayObjman): 545 def __init__(self, ident, parent, modes, zones, **kwargs): 546 self._init_objman(ident, parent=parent, 547 name='Mode OD tables', 548 info='Contains for each transport mode an OD trip table.', 549 xmltag=('modesods', 'modeods', 'ids_mode'), **kwargs) 550 551 self.add_col(am.IdsArrayConf('ids_mode', modes, 552 groupnames=['state'], 553 choices=MODES, 554 name='ID mode', 555 xmltag='vClass', 556 info='ID of transport mode.', 557 )) 558 559 self.add_col(cm.ObjsConf('odtrips', 560 groupnames=['state'], 561 is_save=True, 562 name='OD matrix', 563 info='Matrix with trips from origin to destintion for a specific mode.', 564 )) 565 566 self.add(cm.ObjConf(zones, is_child=False, groups=['_private'])) 567 568 def generate_trips(self, demand, time_start, time_end, **kwargs): 569 for id_od_mode in self.get_ids(): 570 self.odtrips[id_od_mode].generate_trips( 571 demand, time_start, time_end, self.ids_mode[id_od_mode], **kwargs) 572 573 def generate_odflows(self, odflowtab, time_start, time_end, **kwargs): 574 for id_od_mode in self.get_ids(): 575 self.odtrips[id_od_mode].generate_odflows( 576 odflowtab, time_start, time_end, self.ids_mode[id_od_mode], **kwargs) 577 578 def add_od_trips(self, id_mode, scale, names_orig, names_dest, tripnumbers): 579 # print 'OdModes.add_od_trips',id_mode, scale, names_orig, names_dest, tripnumbers 580 ids_mode = self.select_ids(self.ids_mode.get_value() == id_mode) 581 if len(ids_mode) == 0: 582 id_od_modes = self.add_row(ids_mode=id_mode) 583 # print ' create',id_od_modes 584 odtrips = OdTrips((self.odtrips.attrname, id_od_modes), 585 self, self.zones.get_value()) 586 self.odtrips[id_od_modes] = odtrips 587 odtrips.add_od_trips(scale, names_orig, names_dest, tripnumbers) 588 return odtrips 589 else: 590 id_od_modes = ids_mode[0] # modes are unique 591 # print ' use',id_od_modes 592 self.odtrips[id_od_modes].add_od_trips( 593 scale, names_orig, names_dest, tripnumbers) 594 return self.odtrips[id_od_modes] 595 596 597class OdIntervals(am.ArrayObjman): 598 def __init__(self, ident='odintervals', parent=None, net=None, zones=None, **kwargs): 599 self._init_objman(ident, parent=parent, # = demand 600 name='OD Demand', 601 info='Contains origin-to-destination zone transport demand for different time intervals.', 602 xmltag=('odintervals', 'odinteval', None), **kwargs) 603 604 self.add_col(am.ArrayConf('times_start', 0, 605 groupnames=['state'], 606 perm='rw', 607 name='Start time', 608 unit='s', 609 info='Start time of interval in seconds (no fractional seconds).', 610 xmltag='t_start', 611 )) 612 613 self.add_col(am.ArrayConf('times_end', 3600, 614 groupnames=['state'], 615 perm='rw', 616 name='End time', 617 unit='s', 618 info='End time of interval in seconds (no fractional seconds).', 619 xmltag='t_end', 620 )) 621 622 activitytypes = self.parent.activitytypes 623 self.add_col(am.IdsArrayConf('ids_activitytype_orig', activitytypes, 624 groupnames=['parameters'], 625 perm='rw', 626 #choices = activitytypes.names.get_indexmap(), 627 name='Activity type at orig.', 628 symbol='Act. orig.', 629 info='Type of activity performed at origin, before the trip.', 630 #xmltag = 'actType', 631 #xmlmap = get_inversemap( activitytypes.names.get_indexmap()), 632 )) 633 634 self.add_col(am.IdsArrayConf('ids_activitytype_dest', activitytypes, 635 groupnames=['parameters'], 636 perm='rw', 637 #choices = activitytypes.names.get_indexmap(), 638 name='Activity type at dest.', 639 symbol='Act. dest.', 640 info='Type of activity performed at destination, after the trip.', 641 #xmltag = 'actType', 642 #xmlmap = get_inversemap( activitytypes.names.get_indexmap()), 643 )) 644 645 self.add_col(cm.ObjsConf('odmodes', 646 groupnames=['state'], 647 is_save=True, 648 name='OD modes', 649 info='OD transport demand for all transport modes within the respective time interval.', 650 )) 651 self.add(cm.ObjConf(net, is_child=False, groups=['_private'])) 652 self.add(cm.ObjConf(zones, is_child=False, groups=['_private'])) 653 # print 'OdIntervals.__init__',self,dir(self) 654 655 def generate_trips(self, **kwargs): 656 """ 657 Generates trips in trip table. 658 """ 659 # make sure zone edges are up to date 660 self.get_zones().refresh_zoneedges() 661 demand = self.parent 662 for id_inter in self.get_ids(): 663 self.odmodes[id_inter].generate_trips(demand, self.times_start[id_inter], 664 self.times_end[id_inter], 665 **kwargs) 666 667 def generate_odflows(self, **kwargs): 668 """ 669 Generates a flat table with all OD flows. 670 """ 671 odflowtab = OdFlowTable(self, self.get_modes(), 672 self.get_zones(), self.get_activitytypes()) 673 for id_inter in self.get_ids(): 674 self.odmodes[id_inter].generate_odflows(odflowtab, 675 self.times_start[id_inter], 676 self.times_end[id_inter], 677 id_activitytype_orig=self.ids_activitytype_orig[id_inter], 678 id_activitytype_dest=self.ids_activitytype_dest[id_inter], 679 **kwargs) 680 return odflowtab 681 682 def clear_od_trips(self): 683 self.clear() 684 685 def add_od_flows(self, t_start, t_end, id_mode, 686 id_activitytype_orig, id_activitytype_dest, 687 scale, names_orig, names_dest, tripnumbers): 688 689 # print 'OdIntervals.add_od_flows',t_start, t_end, id_mode, scale 690 ids_inter = self.select_ids( 691 (self.times_start.get_value() == t_start) 692 & (self.times_end.get_value() == t_end) 693 & (self.ids_activitytype_orig.get_value() == id_activitytype_orig) 694 & (self.ids_activitytype_dest.get_value() == id_activitytype_dest) 695 ) 696 697 if len(ids_inter) == 0: 698 # no existing interval found. Create a new one 699 id_inter = self.add_row(times_start=t_start, times_end=t_end, 700 ids_activitytype_orig=id_activitytype_orig, 701 ids_activitytype_dest=id_activitytype_dest, 702 ) 703 # print ' create new',id_inter 704 #odintervals.add_rows(2, t_start=[0,3600], t_end=[3600, 7200]) 705 odmodes = OdModes((self.odmodes.attrname, id_inter), parent=self, 706 modes=self.get_net().modes, zones=self.get_zones()) 707 # NO!! odmodes = OdModes( ('ODMs for modes', id_inter), parent = self, modes = self.get_net().modes, zones = self.get_zones()) 708 self.odmodes[id_inter] = odmodes 709 710 odtrips = odmodes.add_od_trips( 711 id_mode, scale, names_orig, names_dest, tripnumbers) 712 return odtrips 713 else: 714 715 # there should be only one demand table found for a certain interval 716 id_inter = ids_inter[0] 717 # print ' use',id_inter 718 odtrips = self.odmodes[id_inter].add_od_trips( 719 id_mode, scale, names_orig, names_dest, tripnumbers) 720 return odtrips 721 722 def add_od_flow(self, t_start, t_end, id_mode, 723 id_activitytype_orig, id_activitytype_dest, 724 scale, 725 name_orig, name_dest, tripnumber): 726 727 # print 'OdIntervals.add_od_flow',t_start, t_end, id_mode, scale, name_orig,name_dest,tripnumber 728 odtrips = self.add_od_flows(t_start, t_end, id_mode, 729 id_activitytype_orig, id_activitytype_dest, 730 scale, 731 [name_orig], [name_dest], [tripnumber]) 732 733 return odtrips 734 735 def get_net(self): 736 return self.net.get_value() 737 738 def get_zones(self): 739 return self.zones.get_value() 740 741 def get_modes(self): 742 return self.net.get_value().modes 743 744 def get_activitytypes(self): 745 return self.parent.activitytypes 746