Tick when time changes rather than on event

This commit is contained in:
Ruben1729 2024-03-12 13:32:47 -04:00
parent 2ab91cfaeb
commit 35ec942d94
5 changed files with 117 additions and 106 deletions

Binary file not shown.

10
main.py
View File

@ -1,3 +1,4 @@
import json
from pathlib import Path from pathlib import Path
from hub.imports.geometry_factory import GeometryFactory from hub.imports.geometry_factory import GeometryFactory
@ -10,7 +11,7 @@ from matsim import Matsim
from matsim_visualizer import MatsimVisualizer from matsim_visualizer import MatsimVisualizer
try: 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' construction_format = 'nrcan'
usage_format = 'nrcan' usage_format = 'nrcan'
energy_systems_format = 'montreal_custom' energy_systems_format = 'montreal_custom'
@ -18,7 +19,7 @@ try:
out_path = (Path(__file__).parent / 'output_files') out_path = (Path(__file__).parent / 'output_files')
city = GeometryFactory('geojson', city = GeometryFactory('geojson',
path=file_path, path=file_path,
height_field='ETAGE_HORS', height_field='citygml_me',
year_of_construction_field='ANNEE_CONS', year_of_construction_field='ANNEE_CONS',
function_field='CODE_UTILI', function_field='CODE_UTILI',
function_to_hub=Dictionaries().montreal_function_to_hub_function).city function_to_hub=Dictionaries().montreal_function_to_hub_function).city
@ -31,10 +32,13 @@ try:
visualizer = MatsimVisualizer( visualizer = MatsimVisualizer(
'output_files/Montreal', 'output_files/Montreal',
'output_files', 'output_files',
(3854635.608067, 6040255.047194, 3855550.392442, 6039416.667303) (3854635.608067, 6040255.047194, 3855550.392442, 6039416.667303),
True
) )
visualizer.visualize() visualizer.visualize()
except Exception as ex: except Exception as ex:
print('error: ', ex) print('error: ', ex)
print('[simulation abort]') print('[simulation abort]')

207
matsim.py
View File

@ -55,60 +55,59 @@ class Matsim:
""" """
Exports the city's facilities data to XML and shapefile formats. 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']) facilities_xml = etree.Element('facilities', name=self._facilities['name'])
for building in self._city.buildings: for building in self._city.buildings:
facility = { try:
'id': building.name, facility = {
'x': str(building.centroid[0]), 'id': building.name,
'y': str(building.centroid[1]), 'x': str(building.centroid[0]),
'activity': [] 'y': str(building.centroid[1]),
} 'activity': []
}
if len(building.thermal_zones_from_internal_zones) > 1: if len(building.thermal_zones_from_internal_zones) > 1:
raise NotImplementedError("multi-zone buildings aren't yet supported") raise NotImplementedError("multi-zone buildings aren't yet supported")
building_schedules = [] building_schedules = []
capacity = 0 capacity = 0
for thermal_zone in building.thermal_zones_from_internal_zones: for thermal_zone in building.thermal_zones_from_internal_zones:
capacity = thermal_zone.occupancy.occupancy_density * building.floor_area * building.storeys_above_ground capacity = thermal_zone.occupancy.occupancy_density * building.floor_area * building.storeys_above_ground
for schedule in thermal_zone.occupancy.occupancy_schedules: for schedule in thermal_zone.occupancy.occupancy_schedules:
building_schedules.append(schedule) building_schedules.append(schedule)
activity_info = { activity_info = {
'type': building.function, 'type': building.function,
'capacity': math.ceil(capacity), 'capacity': math.ceil(capacity),
'opentime': _convert_schedules(building_schedules) 'opentime': _convert_schedules(building_schedules)
} }
facility_xml = etree.SubElement(facilities_xml, 'facility', { facility_xml = etree.SubElement(facilities_xml, 'facility', {
'id': f"{facility['id']}", 'id': f"{facility['id']}",
'x': f"{facility['x']}", 'x': f"{facility['x']}",
'y': f"{facility['y']}", 'y': f"{facility['y']}",
}) })
activity_xml = etree.SubElement(facility_xml, 'activity', { activity_xml = etree.SubElement(facility_xml, 'activity', {
'type': f"{activity_info['type']}" 'type': f"{activity_info['type']}"
}) })
etree.SubElement(activity_xml, 'capacity', { etree.SubElement(activity_xml, 'capacity', {
'value': f"{activity_info['capacity']}" 'value': f"{activity_info['capacity']}"
}) })
etree.SubElement(activity_xml, 'opentime', { etree.SubElement(activity_xml, 'opentime', {
'day': f"{activity_info['opentime'][0]['day']}", 'day': f"{activity_info['opentime'][0]['day']}",
'start_time': f"{activity_info['opentime'][0]['start_time']}", 'start_time': f"{activity_info['opentime'][0]['start_time']}",
'end_time': f"{activity_info['opentime'][0]['end_time']}" 'end_time': f"{activity_info['opentime'][0]['end_time']}"
}) })
facility['activity'].append(activity_info) facility['activity'].append(activity_info)
self._facilities['facility'].append(facility) 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)]) 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. Generates and exports the city's population data to an XML file.
""" """
population = etree.Element("population") try:
id = 0
# Generate work facilities population = etree.Element("population")
work = [] id = 0
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'
})
# Generate the population from residential places first # Generate work facilities
current_work = 0 work = []
for facility in self._facilities['facility']: for facility in self._facilities['facility']:
if facility['activity'][0]['type'] == cte.RESIDENTIAL: if facility['activity'][0]['type'] != cte.RESIDENTIAL:
max_capacity = int(facility['activity'][0]['capacity']) work.append({
for i in range(max_capacity): 'type': facility['activity'][0]['type'],
person = etree.SubElement(population, 'person', { 'capacity': int(facility['activity'][0]['capacity']),
'id': str(id), 'facility': facility['id'],
'sex': 'm', 'x': facility['x'],
'age': '32', 'y': facility['y'],
'car_avail': 'always', 'start_time': '08:00:00',
'employed': 'yes', 'end_time': '18:00:00'
})
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'
}) })
# Leg to work # Generate the population from residential places first
etree.SubElement(plan, 'leg', {'mode': 'car'}) 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 # Residential activity
etree.SubElement(plan, 'act', { etree.SubElement(plan, 'act', {
'type': f"{work[current_work]['type']}", 'type': f"{facility['activity'][0]['type']}",
'facility': f"{work[current_work]['facility']}", 'facility': f"{facility['id']}",
'x': f"{work[current_work]['x']}", 'x': f"{facility['x']}",
'y': f"{work[current_work]['y']}", 'y': f"{facility['y']}",
'start_time': f"{work[current_work]['start_time']}", 'end_time': '7:30:00'
'end_time': f"{work[current_work]['end_time']}", })
})
# Leg to home # Leg to work
etree.SubElement(plan, 'leg', {'mode': 'car'}) etree.SubElement(plan, 'leg', {'mode': 'car'})
# Residential activity (return) # Work activity
etree.SubElement(plan, 'act', { etree.SubElement(plan, 'act', {
'type': f"{facility['activity'][0]['type']}", 'type': f"{work[current_work]['type']}",
'facility': f"{facility['id']}", 'facility': f"{work[current_work]['facility']}",
'x': f"{facility['x']}", 'x': f"{work[current_work]['x']}",
'y': f"{facility['y']}", '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 # Leg to home
if work[current_work]['capacity'] == 0: etree.SubElement(plan, 'leg', {'mode': 'car'})
current_work += 1
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 # Write xml content to file
xml_content = etree.tostring(population, pretty_print=True, encoding='UTF-8').decode('utf-8') xml_content = etree.tostring(population, pretty_print=True, encoding='UTF-8').decode('utf-8')

View File

@ -92,11 +92,14 @@ class MatsimVisualizer:
with gzip.open(self._events_file_path, 'rb') as file: with gzip.open(self._events_file_path, 'rb') as file:
events_doc = etree.parse(file) events_doc = etree.parse(file)
current_time = None
self._tick = 0 self._tick = 0
for event in events_doc.xpath('/events/event'): for event in events_doc.xpath('/events/event'):
link_id = event.get('link') link_id = event.get('link')
event_type = event.get('type') event_type = event.get('type')
time = float(event.get('time')) time = float(event.get('time'))
if current_time is None:
current_time = float(event.get('time'))
ticked = False ticked = False
if link_id is not None and event_type is not None and time is not None: 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 cumulative_traffic[link_id] -= 1
ticked = True ticked = True
if ticked: if ticked and current_time != time:
self._tick += 1 self._tick += 1
current_time = time
def _create_graph(self): def _create_graph(self):
for node_id, coords in self._nodes.items(): for node_id, coords in self._nodes.items():