Skip to content

pam.planner.od

Manages origin-destination data required by the planner module.

Labels #

Bases: NamedTuple

Data labels for the origin-destination dataset.

destination_zones: list instance-attribute #

mode: list instance-attribute #

origin_zones: list instance-attribute #

vars: list instance-attribute #

OD(data, labels) #

Holds origin-destination matrices for a number of modes and variables.

PARAMETER DESCRIPTION
data

A multi-dimensional numpy array of the origin-destination data. - First dimension: variable (ie travel time, distance, etc) - Second dimension: origin zone - Third dimension: destination zone - Fourth dimension: mode (ie car, bus, etc)

TYPE: ndarray

labels

TYPE: Union[Labels, list, dict]

Source code in src/pam/planner/od.py
def __init__(self, data: np.ndarray, labels: Union[Labels, list, dict]) -> None:
    """
    Args:
        data (np.ndarray):
            A multi-dimensional numpy array of the origin-destination data.
            - First dimension: variable (ie travel time, distance, etc)
            - Second dimension: origin zone
            - Third dimension: destination zone
            - Fourth dimension: mode (ie car, bus, etc)
        labels (Union[Labels, list, dict]):
    """
    self.data = data
    self.labels = self.parse_labels(labels)
    self.data_checks()

data = data instance-attribute #

labels = self.parse_labels(labels) instance-attribute #

data_checks() #

Check the integrity of input data and labels.

Source code in src/pam/planner/od.py
def data_checks(self):
    """Check the integrity of input data and labels."""
    assert (
        self.data.ndim == 4
    ), "The number of matrix dimensions should be 4 (mode, variable, origin, destination)"
    for i, (key, labels) in enumerate(zip(self.labels._fields, self.labels)):
        assert len(labels) == self.data.shape[i], (
            f"The number of {key} labels should match the number of elements"
            f"in dimension {i} of the OD dataset"
        )

parse_labels(labels) staticmethod #

Parse labels as a named tuple.

Source code in src/pam/planner/od.py
@staticmethod
def parse_labels(labels: Union[Labels, list, dict]) -> Labels:
    """Parse labels as a named tuple."""
    if not isinstance(labels, Labels):
        if isinstance(labels, list):
            return Labels(*labels)
        elif isinstance(labels, dict):
            return Labels(**labels)
        else:
            raise ValueError("Please provide a valid label type")
    return labels

ODFactory #

check(matrices, labels) staticmethod #

Source code in src/pam/planner/od.py
@staticmethod
def check(matrices: list[ODMatrix], labels: Labels) -> None:
    # all matrices follow the same zoning system and are equal size
    for mat in matrices:
        assert mat.origin_zones == labels.origin_zones, "Please check zone labels"
        assert mat.destination_zones == labels.destination_zones, "Please check zone labels"
        assert mat.matrix.shape == matrices[0].matrix.shape, "Please check matrix dimensions"

    # all possible combinations are provided
    combinations_matrices = [(var, trmode) for (var, trmode, *others) in matrices]
    combinations_labels = list(itertools.product(labels.vars, labels.mode))
    for combination in combinations_labels:
        assert (
            combination in combinations_matrices
        ), f"Combination {combination} missing from the input matrices"

    # no duplicate combinations
    assert len(combinations_matrices) == len(
        set(combinations_matrices)
    ), "No duplicate keys are allowed"

from_matrices(matrices) classmethod #

Creates an OD instance from a list of ODMatrices.

Source code in src/pam/planner/od.py
@classmethod
def from_matrices(cls, matrices: list[ODMatrix]) -> OD:
    """Creates an OD instance from a list of ODMatrices."""
    # collect dimensions
    labels = cls.prepare_labels(matrices)

    cls.check(matrices, labels)

    # create ndarray
    od = np.zeros(shape=[len(x) for x in labels])
    for mat in matrices:
        od[labels.vars.index(mat.var), :, :, labels.mode.index(mat.mode)] = mat.matrix

    return OD(data=od, labels=labels)

prepare_labels(matrices) staticmethod #

Source code in src/pam/planner/od.py
@staticmethod
def prepare_labels(matrices: list[ODMatrix]) -> Labels:
    labels = Labels(
        vars=list(dict.fromkeys(mat.var for mat in matrices)),
        origin_zones=matrices[0].origin_zones,
        destination_zones=matrices[0].destination_zones,
        mode=list(dict.fromkeys(mat.mode for mat in matrices)),
    )
    return labels

ODMatrix #

Bases: NamedTuple

destination_zones: tuple instance-attribute #

matrix: np.array instance-attribute #

mode: str instance-attribute #

origin_zones: tuple instance-attribute #

var: str instance-attribute #