From dff3f4e97ca6db0caf6fbd9cfff80f78029339ca Mon Sep 17 00:00:00 2001 From: mkreuschnervsp Date: Thu, 31 Oct 2024 11:26:34 +0900 Subject: [PATCH] adding py files to create public transit --- src/main/python/create_transitVehicles.py | 94 +++++++++++++++++++++++ src/main/python/merge_transitSchedule.py | 74 ++++++++++++++++++ 2 files changed, 168 insertions(+) create mode 100644 src/main/python/create_transitVehicles.py create mode 100644 src/main/python/merge_transitSchedule.py diff --git a/src/main/python/create_transitVehicles.py b/src/main/python/create_transitVehicles.py new file mode 100644 index 0000000..f9a102a --- /dev/null +++ b/src/main/python/create_transitVehicles.py @@ -0,0 +1,94 @@ +import xml.etree.ElementTree as ET +import xml.dom.minidom as minidom +import csv + +# Define the namespaces +namespaces = { + None: "http://www.matsim.org/files/dtd", # Default namespace + "xsi": "http://www.w3.org/2001/XMLSchema-instance" +} + +# Create the root element with namespaces +root = ET.Element('vehicleDefinitions', { + "xmlns": namespaces[None], + "xmlns:xsi": namespaces["xsi"], + "xsi:schemaLocation": "http://www.matsim.org/files/dtd http://www.matsim.org/files/dtd/vehicleDefinitions_v2.0.xsd" +}) + +# Function to add a new vehicle type based on data from the CSV file +def add_vehicle_type_from_csv(csv_file): + with open(csv_file, newline='') as csvfile: + reader = csv.DictReader(csvfile) + for row in reader: + # Read parameters from the CSV row + vehicle_id = row['vehicle_id'] + access_time = float(row['access_time']) + door_operation = row['door_operation'] + egress_time = float(row['egress_time']) + seats = int(row['seats']) + standing_room = int(row['standing_room']) + length = float(row['length']) + width = float(row['width']) + engine_info = row['engine_info'].lower() == 'true' # Convert to boolean + + # Create vehicle type element + vehicle_type = ET.Element('vehicleType', id=vehicle_id) + + # Attributes for vehicle type + attributes = ET.SubElement(vehicle_type, 'attributes') + ET.SubElement(attributes, 'attribute', attrib={"name": "accessTimeInSecondsPerPerson", "class": "java.lang.Double"}).text = str(access_time) + ET.SubElement(attributes, 'attribute', attrib={"name": "doorOperationMode", "class": "org.matsim.vehicles.VehicleType$DoorOperationMode"}).text = door_operation + ET.SubElement(attributes, 'attribute', attrib={"name": "egressTimeInSecondsPerPerson", "class": "java.lang.Double"}).text = str(egress_time) + + # Capacity, length, width, and other elements + ET.SubElement(vehicle_type, 'capacity', seats=str(seats), standingRoomInPersons=str(standing_room)) + ET.SubElement(vehicle_type, 'length', meter=str(length)) + ET.SubElement(vehicle_type, 'width', meter=str(width)) + + # Engine Information (optional) + if engine_info: + engine_information = ET.SubElement(vehicle_type, 'engineInformation') + engine_attributes = ET.SubElement(engine_information, 'attributes') + ET.SubElement(engine_attributes, 'attribute', attrib={"name": "HbefaEmissionsConcept", "class": "java.lang.String"}).text = "average" + ET.SubElement(engine_attributes, 'attribute', attrib={"name": "HbefaSizeClass", "class": "java.lang.String"}).text = "average" + ET.SubElement(engine_attributes, 'attribute', attrib={"name": "HbefaTechnology", "class": "java.lang.String"}).text = "average" + ET.SubElement(engine_attributes, 'attribute', attrib={"name": "HbefaVehicleCategory", "class": "java.lang.String"}).text = "NON_HBEFA_VEHICLE" + + # Remaining elements + ET.SubElement(vehicle_type, 'costInformation') + ET.SubElement(vehicle_type, 'passengerCarEquivalents', pce="1.0") + ET.SubElement(vehicle_type, 'networkMode', networkMode="car") + ET.SubElement(vehicle_type, 'flowEfficiencyFactor', factor="1.0") + + # Append the completed vehicleType to root + root.append(vehicle_type) + +# Function to add vehicles from CSV data +def add_vehicles_from_csv(csv_file): + with open(csv_file, newline='') as csvfile: + reader = csv.DictReader(csvfile) + for row in reader: + operator = row['operator'] + line_number = row['line_number'] + vehicle_count = int(row['vehicle_count']) + vehicle_type = row['vehicle_type'] + + for i in range(vehicle_count): + vehicle_id = f"pt_{operator}-{line_number}-{i}" + vehicle = ET.Element('vehicle', id=vehicle_id, type=vehicle_type) + root.append(vehicle) + +# Example usage: +# Load vehicle types and vehicles from CSV +add_vehicle_type_from_csv('/Users/mkreuschnervsp/Desktop/kyoto_vehicle_types.csv') +add_vehicles_from_csv('/Users/mkreuschnervsp/Desktop/kyoto_vehicles.csv') + +# Function to prettify and save the XML +def save_pretty_xml(element, filename): + xml_string = ET.tostring(element, encoding='utf-8') + pretty_xml = minidom.parseString(xml_string).toprettyxml(indent=" ") + with open(filename, "w", encoding="utf-8") as file: + file.write(pretty_xml) + +# Save the prettified XML to a file +save_pretty_xml(root, '/Users/mkreuschnervsp/Desktop/matsim-kyoto_transitVehicles_pretty.xml') \ No newline at end of file diff --git a/src/main/python/merge_transitSchedule.py b/src/main/python/merge_transitSchedule.py new file mode 100644 index 0000000..d6d359c --- /dev/null +++ b/src/main/python/merge_transitSchedule.py @@ -0,0 +1,74 @@ +import xml.etree.ElementTree as ET + +def merge_transit_schedules(file1, file2, output_file): + # Parse the XML files + tree1 = ET.parse(file1) + root1 = tree1.getroot() + + tree2 = ET.parse(file2) + root2 = tree2.getroot() + + # Create a new root for the merged document + merged_root = ET.Element("transitSchedule") + + # Copy from the first file + attributes1 = root1.find("attributes") + if attributes1 is not None: + merged_root.append(attributes1) + + # Merge + transitStops = ET.Element("transitStops") + merged_root.append(transitStops) + stop_ids = set() + + def merge_stops(root, stop_ids, transitStops): + for stop in root.findall(".//stopFacility"): + stop_id = stop.get("id") + if stop_id not in stop_ids: + stop_ids.add(stop_id) + transitStops.append(stop) + + # Apply merging of stops from both files + merge_stops(root1, stop_ids, transitStops) + merge_stops(root2, stop_ids, transitStops) + + # Merge + transitLines = ET.Element("transitLines") + merged_root.append(transitLines) + line_ids = set() + + def merge_lines(root, line_ids, transitLines): + for line in root.findall(".//transitLine"): + line_id = line.get("id") + if line_id not in line_ids: + line_ids.add(line_id) + transitLines.append(line) + else: + # If the line already exists, merge its routes + existing_line = [l for l in transitLines if l.get("id") == line_id][0] + route_ids = {r.get("id") for r in existing_line.findall(".//transitRoute")} + + for route in line.findall("transitRoute"): + route_id = route.get("id") + if route_id not in route_ids: + route_ids.add(route_id) + existing_line.append(route) + + # Apply merging of lines and routes from both files + merge_lines(root1, line_ids, transitLines) + merge_lines(root2, line_ids, transitLines) + + # Save the merged XML to the output file + merged_tree = ET.ElementTree(merged_root) + merged_tree.write(output_file, encoding="utf-8", xml_declaration=True) + print(f"Merge complete. Output saved to {output_file}") + +# Paths to your input files and output file +file1 = "/Users/mkreuschnervsp/git/matsim-kyoto/input/kyotobus-transitSchedule.xml" +file2 = "/Users/mkreuschnervsp/git/matsim-kyoto/input/kyotocitybus-transitSchedule.xml" +output_file = "/Users/mkreuschnervsp/git/matsim-kyoto/input/mergedKyoto-transitSchedule.xml" + +merge_transit_schedules(file1, file2, output_file) + + +