Skip to content

pam.vehicles

CapacityType(seats=4, standingRoomInPersons=0) dataclass #

Vehicle capacity dataclass with read/write methods.

ATTRIBUTE DESCRIPTION
seats

Seats in/on vehicle.

TYPE: int

standingRoomInPersons

Standing room in/on vehicle.

TYPE: int

seats: int = 4 class-attribute instance-attribute #

standingRoomInPersons: int = 0 class-attribute instance-attribute #

from_xml_elem(elem) classmethod #

Source code in src/pam/vehicles.py
@classmethod
def from_xml_elem(cls, elem):
    attribs = {k: int(v) for k, v in elem.attrib.items()}
    return cls(**attribs)

to_xml(xf) #

Source code in src/pam/vehicles.py
def to_xml(self, xf):
    xf.write(
        et.Element(
            "capacity",
            {
                "seats": str(self.seats),
                "standingRoomInPersons": str(self.standingRoomInPersons),
            },
        )
    )

ElectricVehicle(vid, type_id, battery_capacity=60, initial_soc=battery_capacity, charger_types='default') dataclass #

Bases: Vehicle

Electric vehicle data representation. Required for MATSim EV extension.

ATTRIBUTE DESCRIPTION
vid

Unique vehicle identifier.

TYPE: str

type_id

Type of vehicle, eg "default_car".

TYPE: str

battery_capacity

Charge capacity.

TYPE: float

initial_soc

Initial state of charge.

TYPE: float

charger_types

Types of chargers vehicle may use.

TYPE: str

battery_capacity: float = 60 class-attribute instance-attribute #

charger_types: str = 'default' class-attribute instance-attribute #

initial_soc: float = battery_capacity class-attribute instance-attribute #

type_id: str instance-attribute #

vid: str instance-attribute #

to_ev_xml(xf) #

Write vehicle to MATSim formatted xml.

PARAMETER DESCRIPTION
xf

Parent xml element.

TYPE: Element

Source code in src/pam/vehicles.py
def to_ev_xml(self, xf) -> None:
    """Write vehicle to MATSim formatted xml.

    Args:
        xf (et.Element): Parent xml element.
    """
    xf.write(
        et.Element(
            "vehicle",
            {
                "id": str(self.vid),
                "battery_capacity": str(self.battery_capacity),
                "initial_soc": str(self.initial_soc),
                "charger_types": str(self.charger_types),
                "vehicle_type": str(self.type_id),
            },
        )
    )

to_xml(xf) #

Write vehicle to MATSim formatted xml.

PARAMETER DESCRIPTION
xf

Parent xml element.

TYPE: Element

Source code in src/pam/vehicles.py
def to_xml(self, xf: et.Element) -> None:
    """Write vehicle to MATSim formatted xml.

    Args:
        xf (et.Element): Parent xml element.
    """
    xf.write(et.Element("vehicle", {"id": str(self.vid), "type": str(self.type_id)}))

Vehicle(vid, type_id) dataclass #

Vehicle parent data class, holds required vehicle data (id and type) and read/write methods.

ATTRIBUTE DESCRIPTION
vid

Unique vehicle identifier.

TYPE: str

type_id

Type of vehicle, eg "default_car".

TYPE: str

type_id: str instance-attribute #

vid: str instance-attribute #

to_xml(xf) #

Write vehicle to MATSim formatted xml.

PARAMETER DESCRIPTION
xf

Parent xml element.

TYPE: Element

Source code in src/pam/vehicles.py
def to_xml(self, xf: et.Element) -> None:
    """Write vehicle to MATSim formatted xml.

    Args:
        xf (et.Element): Parent xml element.
    """
    xf.write(et.Element("vehicle", {"id": str(self.vid), "type": str(self.type_id)}))

VehicleManager() #

Vehicles and vehicle types representation, responsible for read/write from MATSim vehicles files.

ATTRIBUTE DESCRIPTION
_veh_types

Mapping of type ids to vehicle types data.

TYPE: dict[str, VehicleType]

_vehicles

Mapping of vehicle ids to vehicle data.

TYPE: dict[str, Vehicle]

Source code in src/pam/vehicles.py
def __init__(self) -> None:
    self._veh_types = {}
    self._vehicles = {}

evs: dict[str, ElectricVehicle] property #

Return dictionary of electric vehicles in manager.

RETURNS DESCRIPTION
dict[str, ElectricVehicle]

dict[str, ElectricVehicle]: Dictionary of electric vehicles.

add_type(vehicle_type) #

Add vehicle type to manager.

PARAMETER DESCRIPTION
vehicle_type

Vehicle type dataclass.

TYPE: VehicleType

Source code in src/pam/vehicles.py
def add_type(self, vehicle_type: VehicleType) -> None:
    """Add vehicle type to manager.

    Args:
        vehicle_type (VehicleType): Vehicle type dataclass.
    """
    if vehicle_type.id in self._veh_types:
        logging.info(f"Warning, overwriting existing vehicle type '{vehicle_type.id}'.")
    self._veh_types[vehicle_type.id] = vehicle_type

add_veh(v) #

Add vehicle to manager.

PARAMETER DESCRIPTION
v

Vehicle dataclass.

TYPE: Vehicle

RAISES DESCRIPTION
PAMVehicleIdError

Unknown vehicle type.

Source code in src/pam/vehicles.py
def add_veh(self, v: Vehicle):
    """Add vehicle to manager.

    Args:
        v (Vehicle): Vehicle dataclass.

    Raises:
        PAMVehicleIdError: Unknown vehicle type.
    """
    if v.type_id not in self._veh_types:
        raise PAMVehicleTypeError(
            f"Failed to add vehicle: {v.vid}, the vehicle type '{v.type_id}' is an unknown veh type."
        )
    if v.vid in self._vehicles:
        logging.info(f"Warning, overwriting existing vehicle: '{v.vid}'.")
    self._vehicles[v.vid] = v

charger_types() #

Return set of electric charger types used by evs.

RETURNS DESCRIPTION
set[str]

set[str]: Electric charger types.

Source code in src/pam/vehicles.py
def charger_types(self) -> set[str]:
    """Return set of electric charger types used by evs.

    Returns:
        set[str]: Electric charger types.
    """
    chargers = set()
    for v in self.evs.values():
        chargers |= set(v.charger_types.split(","))
    return chargers

clear_types() #

Remove all types from manager.

Source code in src/pam/vehicles.py
def clear_types(self):
    """Remove all types from manager."""
    self._veh_types = {}

clear_vehs() #

Remove all vehciles from manager.

Source code in src/pam/vehicles.py
def clear_vehs(self):
    """Remove all vehciles from manager."""
    self._vehicles = {}

evs_from_xml(path) #

Reads vehicles from MATSim vehicles file (https://www.matsim.org/files/dtd/vehicleDefinitions_v2.0.xsd).

PARAMETER DESCRIPTION
path

path to matsim all_vehicles xml file

TYPE: str

Source code in src/pam/vehicles.py
def evs_from_xml(self, path):
    """Reads vehicles from MATSim vehicles file (https://www.matsim.org/files/dtd/vehicleDefinitions_v2.0.xsd).

    Args:
        path (str): path to matsim all_vehicles xml file
    """
    evs = {}
    for vehicle_elem in utils.get_elems(path, "vehicle"):
        attribs = dict(vehicle_elem.attrib)
        vid = attribs.pop("id")
        vehicle_type = attribs.pop("vehicle_type")
        attribs["battery_capacity"] = float(attribs["battery_capacity"])
        attribs["initial_soc"] = float(attribs["initial_soc"])
        evs[vid] = ElectricVehicle(vid=vid, type_id=vehicle_type, **attribs)
    keys = set(evs) & set(self._vehicles)
    if keys:
        PAMVehicleIdError(
            f"Failed to read evs from xml due to duplicate keys with existing: {keys}"
        )
    self._vehicles.update(evs)

from_xml(vehs_path, evs_path=None) #

Reads MATSim vehicles from https://www.matsim.org/files/dtd/vehicleDefinitions_v2.0.xsd and reads electric_vehicles from https://www.matsim.org/files/dtd/electric_vehicles_v1.dtd. Requires a vehicles file to load an evs file because the electric vehicle type is expected to be defined in the vehicles input.

PARAMETER DESCRIPTION
vehs_path

path to matsim all_vehicles xml file

TYPE: str

evs_path

optional path to matsim electric_vehicles xml file. Defaults to None.

TYPE: Optional[str] DEFAULT: None

RAISES DESCRIPTION
UserWarning

Cannot load evs without a vehs file.

UserWarning

Fails consistency check.

Source code in src/pam/vehicles.py
def from_xml(self, vehs_path: str, evs_path: Optional[str] = None):
    """Reads MATSim vehicles from https://www.matsim.org/files/dtd/vehicleDefinitions_v2.0.xsd
    and reads electric_vehicles from https://www.matsim.org/files/dtd/electric_vehicles_v1.dtd.
    Requires a vehicles file to load an evs file because the electric vehicle type is expected to be defined in
    the vehicles input.

    Args:
        vehs_path (str): path to matsim all_vehicles xml file
        evs_path (Optional[str], optional): optional path to matsim electric_vehicles xml file. Defaults to None.

    Raises:
        UserWarning: Cannot load evs without a vehs file.
        UserWarning: Fails consistency check.
    """

    if not vehs_path and evs_path:
        raise UserWarning("Cannot load an evs file without a vehs file.")
    self.types_from_xml(vehs_path)
    self.vehs_from_xml(vehs_path)
    if evs_path is not None:
        self.evs_from_xml(evs_path)
    if not self.is_consistent():
        raise UserWarning("Inputs not consistent, refer to log.")

get(k, default=None) #

Source code in src/pam/vehicles.py
def get(self, k: str, default: Optional[Vehicle] = None) -> Optional[Vehicle]:
    return self._vehicles.get(k, default)

is_consistent() #

Check that manager vehicle population and types are consistent.

RAISES DESCRIPTION
PAMVehicleIdError

Unknown vehicle type.

RETURNS DESCRIPTION
bool

Manager is consistent. Note that this doesn't check for unused types.

TYPE: bool

Source code in src/pam/vehicles.py
def is_consistent(self) -> bool:
    """Check that manager vehicle population and types are consistent.

    Raises:
        PAMVehicleIdError: Unknown vehicle type.

    Returns:
        bool: Manager is consistent. Note that this doesn't check for unused types.
    """
    veh_types = set(self._veh_types.keys())
    for k, v in self._vehicles.items():
        if v.type_id not in veh_types:
            raise PAMVehicleIdError(
                f"Failed to find veh type of id '{v}', specified for veh id '{k}'."
            )
    return True

len() #

Number of vehicles.

Source code in src/pam/vehicles.py
def len(self) -> int:
    """Number of vehicles."""
    return len(self._vehicles)

pop(vid) #

Source code in src/pam/vehicles.py
def pop(self, vid):
    return self._vehicles.pop(vid)

redundant_types() #

Check for ununsed vehicle types.

RETURNS DESCRIPTION
dict

unused types.

TYPE: dict

Source code in src/pam/vehicles.py
def redundant_types(self) -> dict:
    """Check for ununsed vehicle types.

    Returns:
        dict: unused types.
    """
    unused = {}
    veh_types = set(self._veh_types.keys())
    veh_veh_types = set([v.type_id for v in self._vehicles.values()])
    for t in veh_types:
        if t not in veh_veh_types:
            unused[t] = self._veh_types[t]
    return unused

remove_type(tid) #

Remove vehicle type.

PARAMETER DESCRIPTION
tid

Vehicle type id.

TYPE: str

Source code in src/pam/vehicles.py
def remove_type(self, tid: str):
    """Remove vehicle type.

    Args:
        tid (str): Vehicle type id.
    """
    logging.info("Warning, removing a vehicle type may invalidate your vehicles.")
    if self._veh_types.pop(tid, None) is None:
        raise PAMVehicleTypeError(f"Failed to remove vehicle type {tid}, id not found.")

to_ev_xml(path) #

Writes MATSim electric vehciles file as per https://www.matsim.org/files/dtd/electric_vehicles_v1.dtd.

PARAMETER DESCRIPTION
path

name of output file

TYPE: str

Source code in src/pam/vehicles.py
def to_ev_xml(self, path: str):
    """Writes MATSim electric vehciles file as per https://www.matsim.org/files/dtd/electric_vehicles_v1.dtd.

    Args:
        path (str): name of output file
    """
    with et.xmlfile(path, encoding="utf-8") as xf:
        logging.info(f"Writing electric vehicles to {path}")
        xf.write_declaration(
            doctype='<!DOCTYPE vehicles SYSTEM "http://matsim.org/files/dtd/electric_vehicles_v1.dtd">'
        )
        with xf.element("vehicles"):
            for veh in self.evs.values():
                veh.to_ev_xml(xf)

to_veh_xml(path) #

Writes MATSim vehicles file as per https://www.matsim.org/files/dtd/vehicleDefinitions_v2.0.xsd.

PARAMETER DESCRIPTION
path

name of output file.

TYPE: str

Source code in src/pam/vehicles.py
def to_veh_xml(self, path: str):
    """Writes MATSim vehicles file as per https://www.matsim.org/files/dtd/vehicleDefinitions_v2.0.xsd.

    Args:
        path (str): name of output file.
    """
    with et.xmlfile(path, encoding="utf-8") as xf:
        xf.write_declaration()
        vehicleDefinitions_attribs = {
            "xmlns": "http://www.matsim.org/files/dtd",
            "xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
            "xsi:schemaLocation": "http://www.matsim.org/files/dtd "
            "http://www.matsim.org/files/dtd/vehicleDefinitions_v2.0.xsd",
        }
        with xf.element("vehicleDefinitions", vehicleDefinitions_attribs):
            logging.info(f"Writing vehicle types to {path}")
            for vehicle_type in self._veh_types.values():
                vehicle_type.to_xml(xf)
            logging.info(f"Writing vehicles to {path}")
            for veh in self._vehicles.values():
                veh.to_xml(xf)

to_xml(vehs_path, evs_path=None) #

Write manager to MATSim formatted xml.

PARAMETER DESCRIPTION
vehs_path

Write path for MATSim vehicles file.

TYPE: str

evs_path

Write path for MATSim electric vehicles file. Defaults to None.

TYPE: Optional[str] DEFAULT: None

Source code in src/pam/vehicles.py
def to_xml(self, vehs_path: str, evs_path: Optional[str] = None):
    """Write manager to MATSim formatted xml.

    Args:
        vehs_path (str): Write path for MATSim vehicles file.
        evs_path (Optional[str], optional): Write path for MATSim electric vehicles file. Defaults to None.
    """
    self.to_veh_xml(vehs_path)
    if evs_path:
        self.to_ev_xml(evs_path)

types_from_xml(path) #

Reads vehicle types from MATSim vehicles file (https://www.matsim.org/files/dtd/vehicleDefinitions_v2.0.xsd).

PARAMETER DESCRIPTION
path

path to matsim all_vehicles xml file

TYPE: str

Source code in src/pam/vehicles.py
def types_from_xml(self, path: str):
    """Reads vehicle types from MATSim vehicles file (https://www.matsim.org/files/dtd/vehicleDefinitions_v2.0.xsd).

    Args:
        path (str): path to matsim all_vehicles xml file
    """
    vehs = dict(
        (elem.get("id"), VehicleType.from_xml_elem(elem))
        for elem in utils.get_elems(path, "vehicleType")
    )
    keys = set(vehs) & set(self._veh_types)
    if keys:
        raise PAMVehicleIdError(
            f"Failed to read types from xml due to duplicate keys with existing types: {keys}"
        )
    self._veh_types.update(vehs)

vehs_from_xml(path) #

Reads vehicles from MATSim vehicles file (https://www.matsim.org/files/dtd/vehicleDefinitions_v2.0.xsd).

PARAMETER DESCRIPTION
path

path to matsim all_vehicles xml file

TYPE: str

Source code in src/pam/vehicles.py
def vehs_from_xml(self, path: str):
    """Reads vehicles from MATSim vehicles file (https://www.matsim.org/files/dtd/vehicleDefinitions_v2.0.xsd).

    Args:
        path (str): path to matsim all_vehicles xml file
    """

    vehs = {
        elem.get("id"): Vehicle(vid=elem.get("id"), type_id=elem.get("type"))
        for elem in utils.get_elems(path, "vehicle")
    }
    keys = set(vehs) & set(self._vehicles)
    if keys:
        raise PAMVehicleIdError(
            f"Failed to read vehs from xml due to duplicate keys with existing: {keys}"
        )
    self._vehicles.update(vehs)

VehicleType(id, length=7.5, width=1.0, networkMode='car', capacity=CapacityType(), description='personal_vehicle', passengerCarEquivalents=1.0, flowEfficiencyFactor=1.0) dataclass #

Vehicle type data with read/write methods.

ATTRIBUTE DESCRIPTION
id

type id.

TYPE: str

length

Vehicle length in m.

TYPE: float

width

Vehicle width in m.

TYPE: float

networkMode

MATSim network mode (used for routing).

TYPE: str

capacity

Vehicle seating and standing capacity.

TYPE: CapacityType

description

Vehicle description.

TYPE: str

passengerCarEquivalents

Vehicle size as passenger car equivalents (PCUs).

TYPE: float

flowEfficiencyFactor

Vehicle flow efficiency factor.

TYPE: float

capacity: CapacityType = field(default_factory=CapacityType) class-attribute instance-attribute #

description: str = 'personal_vehicle' class-attribute instance-attribute #

flowEfficiencyFactor: float = 1.0 class-attribute instance-attribute #

id: str instance-attribute #

length: float = 7.5 class-attribute instance-attribute #

networkMode: str = 'car' class-attribute instance-attribute #

passengerCarEquivalents: float = 1.0 class-attribute instance-attribute #

width: float = 1.0 class-attribute instance-attribute #

from_xml_elem(elem) classmethod #

Construct VehicleType from MATSim xml element.

PARAMETER DESCRIPTION
elem

MATSim formatted vehicle type xml element.

TYPE: Element

RETURNS DESCRIPTION
VehicleType

Vehicle type dataclass.

TYPE: VehicleType

Source code in src/pam/vehicles.py
@classmethod
def from_xml_elem(cls, elem: et.Element) -> VehicleType:
    """Construct VehicleType from MATSim xml element.

    Args:
        elem (et.Element): MATSim formatted vehicle type xml element.

    Returns:
        VehicleType: Vehicle type dataclass.
    """
    attribs = {
        attrib.tag.replace("{http://www.matsim.org/files/dtd}", ""): attrib for attrib in elem
    }
    return cls(
        id=elem.get("id"),
        length=float(attribs["length"].attrib["meter"]),
        width=float(attribs["width"].attrib["meter"]),
        passengerCarEquivalents=float(attribs["passengerCarEquivalents"].attrib["pce"]),
        networkMode=attribs["networkMode"].attrib["networkMode"],
        flowEfficiencyFactor=float(attribs["flowEfficiencyFactor"].attrib["factor"]),
        capacity=CapacityType.from_xml_elem(attribs["capacity"]),
        description=attribs["description"].text,
    )

to_xml(xf) #

Write vehicle type to MATSim formatted xml.

PARAMETER DESCRIPTION
xf

Parent xml element.

TYPE: Element

Source code in src/pam/vehicles.py
def to_xml(self, xf: et.Element) -> None:
    """Write vehicle type to MATSim formatted xml.

    Args:
        xf (et.Element): Parent xml element.
    """
    with xf.element("vehicleType", {"id": self.id}):
        rec = et.Element("description")
        rec.text = self.description
        xf.write(rec)
        self.capacity.to_xml(xf)
        xf.write(et.Element("length", {"meter": str(self.length)}))
        xf.write(et.Element("width", {"meter": str(self.width)}))
        xf.write(
            et.Element("passengerCarEquivalents", {"pce": str(self.passengerCarEquivalents)})
        )
        xf.write(et.Element("networkMode", {"networkMode": str(self.networkMode)}))
        xf.write(et.Element("flowEfficiencyFactor", {"factor": str(self.flowEfficiencyFactor)}))