From 35ec942d947ce05641a5336bafd16f85e346c4ce Mon Sep 17 00:00:00 2001 From: Ruben1729 Date: Tue, 12 Mar 2024 13:32:47 -0400 Subject: [PATCH] Tick when time changes rather than on event --- __pycache__/matsim.cpython-39.pyc | Bin 11259 -> 11384 bytes __pycache__/matsim_visualizer.cpython-39.pyc | Bin 7247 -> 7313 bytes main.py | 10 +- matsim.py | 207 ++++++++++--------- matsim_visualizer.py | 6 +- 5 files changed, 117 insertions(+), 106 deletions(-) diff --git a/__pycache__/matsim.cpython-39.pyc b/__pycache__/matsim.cpython-39.pyc index 0a7fc622a38c599384bf21db8558278c9b72df79..0c7f12c1c76d4d8866ef09ab6db1c0cce7089d78 100644 GIT binary patch delta 2200 zcmZ{lU2GIp6vyYz$L{RTes%k~-R*XFDJ@e9E?BG(rD9v8fNg;iuz+>#9X7kP+wScY z+B!p(f+hyAauZ)HNePmO4}NXplg5znY}5xI_Q?lLjERvK6N6DaXSPylwCVirx#yg@ z_s;pBnf>F~@5cifzuzms-}`reGG5&CN#KF9puw~UuIaQW2&RxHlvqMuq+&#%(iPFh znUt4%g(Y(8qAf0w`Gc02S4AUrrPa>DYxA0Q^IDwKI^2-pK>`s09zn%Na4PF@ z<`T}22@A!TESPmmWNw8Bwnl{cI65?Ne&R0Fn7C zzCNXfgh;A%$Jb9>t+-JK4+W-(&0h<2*ZRSMm-9X>!~3u#&Zqb{fgL2l-N7E`jMkUS#j?YygM z?8u|#U03}3YWm4t=`{S`SGTQNx_eCx=Ejmd6mL}u{!3Mg)bmidXTi~JT@p%Fmd1^2 zS)Q1rMp+umur(2NS7rHiHzjZ*yi=F|GhT=B4S<1R)`s>bgljXhgMS$Xl^WD783Hvb^HX}b;Ph!=$# z%COADG&8_a)|fG!qej8ZWyW>sHoR`|GEK6aImc$X92<;ZfGk+(A`H+(J1b2Dj!WQR zCwMVdO-}GjvCi7pox~AsY}u(|mY)ep@jI=ZDz>w(vgi4q ztvj?qTx9|g=XX*K%5E?};v;R_$nMhRwqHe;(}IWiYwcYMcJkN!i}qwETDmwepvTJY z(NQ`%Hag0l!bOfEZX(_TjCkOaJC!NW%rx7}!OxJyK>}p!UF15=BAC!5<~_Vwspifl$#B3L=#v0+nxy zWz?jC+$+3AhEJ3wODZU)1JFs8h%iTLvIAwv;+&VuvZ;dKHAkr91({ti-Bg_;*T7p= zs8YtguGwB;xU=lEoCQz83kF|E0MtSPxY6bZzgAW)WwFjumk1H2-kvfcqTUQF1}(=D zF+-LD2e{^?vda_}!(G@a;PBWE z53Q#G%SG!S+lf%K2f-QyHlSV_vJNd7x^D=E-_mG(!fXXoazUceIhhDF#rxDuoi0|zJgus^ z>_jnZvT6Q~x?W*nm=k_a9o~roiy%Y+bjkLt8dwZnafBv-s`8>Sb}`GE`G6}KPM|r7 zkOI&}whk8luIq}F*4I~JZYSa0o;%^t`HT56njg=VMoP~cli3k!mb3|?&?HR(r5@S}l)8aRFR->AR$oB_ zX#-H|G5waua?_1w9a!3c(S*%t`zb-!`Fr)Fr~XOH8qyx9oxApQcEbMywW}uS&Q%tf z6AN1*y+$F=1X3i-OM#wQo9{J2NO4sf%jT+bae`*6(x}1yM!sV?{hCdy&5{4p-v~(u z*haig8^R_8U_98Zb%2=G>zRzEE!+ym&g=%UD&@z`s=|!%T$b%e-!_E92uBd`EyPp= z2f|T+s+Q@`oIY`A;8=fpq<5fK_c9Oq&LD*OZ^5nGpGEN;!byZQ0(N>CG?W4WH{mHU z072&GLIvWj+z)*rkqm#OaT{sipEtfniu}pQB?lJ9rudhU94YZsbede`^U>#EO8$r* zAk%zzEEAoE5M3N{y=3G~7|x72qipHi+O>ziX~=nBi=$xel^~|{j!~!U4aE=VfXSZ!2YXXU}tUTkY{2tI}Ya# z_pEm0 zDBsrdGckA~QEdKSc7w3<`^qPY9-{QAel=71HJKuV$T!^E?qmzdX;AEez|QMZ)iG(X z?6|oau(oM8Anq1{rr|^gs!H&S&TdqSt=GuxB{11znTGeyN?L|{bO*cr*vsBT$qrt* z$l7yWhmZw4$No`-bL2-3$x9g8N5Q`G!F%AB1YRMP@eN-S(#rR@b*nhqy2_sBGi^KC zPk_Sm2v{>qAgme2ePFxGziaCv`zo&XpG1c}u_yV%O*<7F`TKm&=43ZYx|mMu@v3uV zgief(jIh0!?HPm*5EcQ3T<~(9G{&h>Vm%V6Dnymx^P{yu5*-eF!;(g9rx@ co($Qxo(p{&0L8{|1 zgfW4!`RpStI5q~#B3iTA{ixS0!5@& z4)c;8XOO)2xbcIr_#{(s?euhTH`WKyH0c{O{_79>`oG!(X!t|;hEcy_nQ3{^M%qY5=xdl+yqQ{E5CoiC-x%z}-W2N`MQVjrE`C8y%O}AIobVAEzmPs?R``zv;VB h!-PAiyFKwafHT)hWJS2;&&D%6a5r@W3q05L@eTK#g}nd( delta 458 zcmZWl&r1S96rQ)XYP;^NuDj|g9jbHJQV0SIqLXwDqO8@xAjm8VMm*Rt$eL3i?FvFP@ZNmy@!t1+GbfqnG|elDMDX-BJ`1IhD>^Px4a*?L zEXK~gGb3ILHIb1OgN0gtD{R9YS^lmnOlbwJhz(WhAq|mQ33xbaLmjGNORq*4wa6|s zgmRau0~8)0)iU--!&fdcQi@?1CSg=0Cb0rj#7Cxy6+;fW_P2?HaV9frl1+EH*~e%x z&M4-DON6(%HHo5ePoVi diff --git a/main.py b/main.py index 2a5ae59..c145760 100644 --- a/main.py +++ b/main.py @@ -1,3 +1,4 @@ +import json from pathlib import Path from hub.imports.geometry_factory import GeometryFactory @@ -10,7 +11,7 @@ from matsim import Matsim from matsim_visualizer import MatsimVisualizer try: - file_path = (Path(__file__).parent / 'input_files' / 'mtlbld_v4.geojson') + file_path = (Path(__file__).parent / 'input_files' / 'summerschool_all_buildings.geojson') construction_format = 'nrcan' usage_format = 'nrcan' energy_systems_format = 'montreal_custom' @@ -18,7 +19,7 @@ try: out_path = (Path(__file__).parent / 'output_files') city = GeometryFactory('geojson', path=file_path, - height_field='ETAGE_HORS', + height_field='citygml_me', year_of_construction_field='ANNEE_CONS', function_field='CODE_UTILI', function_to_hub=Dictionaries().montreal_function_to_hub_function).city @@ -31,10 +32,13 @@ try: visualizer = MatsimVisualizer( 'output_files/Montreal', 'output_files', - (3854635.608067, 6040255.047194, 3855550.392442, 6039416.667303) + (3854635.608067, 6040255.047194, 3855550.392442, 6039416.667303), + True ) visualizer.visualize() except Exception as ex: print('error: ', ex) print('[simulation abort]') + + diff --git a/matsim.py b/matsim.py index f08cced..b11eede 100644 --- a/matsim.py +++ b/matsim.py @@ -55,60 +55,59 @@ class Matsim: """ Exports the city's facilities data to XML and shapefile formats. """ - buildings_shape_data = { - 'id': [], - 'geometry': [] - } facilities_xml = etree.Element('facilities', name=self._facilities['name']) for building in self._city.buildings: - facility = { - 'id': building.name, - 'x': str(building.centroid[0]), - 'y': str(building.centroid[1]), - 'activity': [] - } + try: + facility = { + 'id': building.name, + 'x': str(building.centroid[0]), + 'y': str(building.centroid[1]), + 'activity': [] + } - if len(building.thermal_zones_from_internal_zones) > 1: - raise NotImplementedError("multi-zone buildings aren't yet supported") + if len(building.thermal_zones_from_internal_zones) > 1: + raise NotImplementedError("multi-zone buildings aren't yet supported") - building_schedules = [] + building_schedules = [] - capacity = 0 - for thermal_zone in building.thermal_zones_from_internal_zones: - capacity = thermal_zone.occupancy.occupancy_density * building.floor_area * building.storeys_above_ground - for schedule in thermal_zone.occupancy.occupancy_schedules: - building_schedules.append(schedule) + capacity = 0 + for thermal_zone in building.thermal_zones_from_internal_zones: + capacity = thermal_zone.occupancy.occupancy_density * building.floor_area * building.storeys_above_ground + for schedule in thermal_zone.occupancy.occupancy_schedules: + building_schedules.append(schedule) - activity_info = { - 'type': building.function, - 'capacity': math.ceil(capacity), - 'opentime': _convert_schedules(building_schedules) - } + activity_info = { + 'type': building.function, + 'capacity': math.ceil(capacity), + 'opentime': _convert_schedules(building_schedules) + } - facility_xml = etree.SubElement(facilities_xml, 'facility', { - 'id': f"{facility['id']}", - 'x': f"{facility['x']}", - 'y': f"{facility['y']}", - }) + facility_xml = etree.SubElement(facilities_xml, 'facility', { + 'id': f"{facility['id']}", + 'x': f"{facility['x']}", + 'y': f"{facility['y']}", + }) - activity_xml = etree.SubElement(facility_xml, 'activity', { - 'type': f"{activity_info['type']}" - }) + activity_xml = etree.SubElement(facility_xml, 'activity', { + 'type': f"{activity_info['type']}" + }) - etree.SubElement(activity_xml, 'capacity', { - 'value': f"{activity_info['capacity']}" - }) + etree.SubElement(activity_xml, 'capacity', { + 'value': f"{activity_info['capacity']}" + }) - etree.SubElement(activity_xml, 'opentime', { - 'day': f"{activity_info['opentime'][0]['day']}", - 'start_time': f"{activity_info['opentime'][0]['start_time']}", - 'end_time': f"{activity_info['opentime'][0]['end_time']}" - }) + etree.SubElement(activity_xml, 'opentime', { + 'day': f"{activity_info['opentime'][0]['day']}", + 'start_time': f"{activity_info['opentime'][0]['start_time']}", + 'end_time': f"{activity_info['opentime'][0]['end_time']}" + }) - facility['activity'].append(activity_info) - self._facilities['facility'].append(facility) + facility['activity'].append(activity_info) + self._facilities['facility'].append(facility) + except Exception as ex: + print('error: ', ex) viewport = Polygon([(MONTREAL_LEFT, MONTREAL_TOP), (MONTREAL_RIGHT, MONTREAL_TOP), (MONTREAL_RIGHT, MONTREAL_BOTTOM), (MONTREAL_LEFT, MONTREAL_BOTTOM)]) @@ -142,76 +141,80 @@ class Matsim: """ Generates and exports the city's population data to an XML file. """ - population = etree.Element("population") - id = 0 + try: - # Generate work facilities - work = [] - for facility in self._facilities['facility']: - if facility['activity'][0]['type'] != cte.RESIDENTIAL: - work.append({ - 'type': facility['activity'][0]['type'], - 'capacity': int(facility['activity'][0]['capacity']), - 'facility': facility['id'], - 'x': facility['x'], - 'y': facility['y'], - 'start_time': '08:00:00', - 'end_time': '18:00:00' - }) + population = etree.Element("population") + id = 0 - # Generate the population from residential places first - current_work = 0 - for facility in self._facilities['facility']: - if facility['activity'][0]['type'] == cte.RESIDENTIAL: - max_capacity = int(facility['activity'][0]['capacity']) - for i in range(max_capacity): - person = etree.SubElement(population, 'person', { - 'id': str(id), - 'sex': 'm', - 'age': '32', - 'car_avail': 'always', - 'employed': 'yes', - }) - plan = etree.SubElement(person, 'plan', {'selected': 'yes'}) - - # Residential activity - etree.SubElement(plan, 'act', { - 'type': f"{facility['activity'][0]['type']}", - 'facility': f"{facility['id']}", - 'x': f"{facility['x']}", - 'y': f"{facility['y']}", - 'end_time': '7:30:00' + # Generate work facilities + work = [] + for facility in self._facilities['facility']: + if facility['activity'][0]['type'] != cte.RESIDENTIAL: + work.append({ + 'type': facility['activity'][0]['type'], + 'capacity': int(facility['activity'][0]['capacity']), + 'facility': facility['id'], + 'x': facility['x'], + 'y': facility['y'], + 'start_time': '08:00:00', + 'end_time': '18:00:00' }) - # Leg to work - etree.SubElement(plan, 'leg', {'mode': 'car'}) + # Generate the population from residential places first + current_work = 0 + for facility in self._facilities['facility']: + if facility['activity'][0]['type'] == cte.RESIDENTIAL: + max_capacity = int(facility['activity'][0]['capacity']) + for i in range(max_capacity): + person = etree.SubElement(population, 'person', { + 'id': str(id), + 'sex': 'm', + 'age': '32', + 'car_avail': 'always', + 'employed': 'yes', + }) + plan = etree.SubElement(person, 'plan', {'selected': 'yes'}) - # Work activity - etree.SubElement(plan, 'act', { - 'type': f"{work[current_work]['type']}", - 'facility': f"{work[current_work]['facility']}", - 'x': f"{work[current_work]['x']}", - 'y': f"{work[current_work]['y']}", - 'start_time': f"{work[current_work]['start_time']}", - 'end_time': f"{work[current_work]['end_time']}", - }) + # Residential activity + etree.SubElement(plan, 'act', { + 'type': f"{facility['activity'][0]['type']}", + 'facility': f"{facility['id']}", + 'x': f"{facility['x']}", + 'y': f"{facility['y']}", + 'end_time': '7:30:00' + }) - # Leg to home - etree.SubElement(plan, 'leg', {'mode': 'car'}) + # Leg to work + etree.SubElement(plan, 'leg', {'mode': 'car'}) - # Residential activity (return) - etree.SubElement(plan, 'act', { - 'type': f"{facility['activity'][0]['type']}", - 'facility': f"{facility['id']}", - 'x': f"{facility['x']}", - 'y': f"{facility['y']}", - }) + # Work activity + etree.SubElement(plan, 'act', { + 'type': f"{work[current_work]['type']}", + 'facility': f"{work[current_work]['facility']}", + 'x': f"{work[current_work]['x']}", + 'y': f"{work[current_work]['y']}", + 'start_time': f"{work[current_work]['start_time']}", + 'end_time': f"{work[current_work]['end_time']}", + }) - work[current_work]['capacity'] -= 1 - if work[current_work]['capacity'] == 0: - current_work += 1 + # Leg to home + etree.SubElement(plan, 'leg', {'mode': 'car'}) - id += 1 + # Residential activity (return) + etree.SubElement(plan, 'act', { + 'type': f"{facility['activity'][0]['type']}", + 'facility': f"{facility['id']}", + 'x': f"{facility['x']}", + 'y': f"{facility['y']}", + }) + + work[current_work]['capacity'] -= 1 + if work[current_work]['capacity'] == 0: + current_work += 1 + + id += 1 + except Exception as ex: + print('error: ', ex) # Write xml content to file xml_content = etree.tostring(population, pretty_print=True, encoding='UTF-8').decode('utf-8') diff --git a/matsim_visualizer.py b/matsim_visualizer.py index 501688f..d5b87f8 100644 --- a/matsim_visualizer.py +++ b/matsim_visualizer.py @@ -92,11 +92,14 @@ class MatsimVisualizer: with gzip.open(self._events_file_path, 'rb') as file: events_doc = etree.parse(file) + current_time = None self._tick = 0 for event in events_doc.xpath('/events/event'): link_id = event.get('link') event_type = event.get('type') time = float(event.get('time')) + if current_time is None: + current_time = float(event.get('time')) ticked = False if link_id is not None and event_type is not None and time is not None: @@ -115,8 +118,9 @@ class MatsimVisualizer: cumulative_traffic[link_id] -= 1 ticked = True - if ticked: + if ticked and current_time != time: self._tick += 1 + current_time = time def _create_graph(self): for node_id, coords in self._nodes.items():