Skip to content

Outputs

HtmlOutputConfig

Bases: PrettyModel

Configuration for HTML outputs.

Source code in src/passengersim/config/outputs.py
class HtmlOutputConfig(PrettyModel, extra="forbid", validate_assignment=True):
    """Configuration for HTML outputs."""

    filename: pathlib.Path | bool | None = None
    """Write HTML outputs to this file after a run.

    If this is None or False, no HTML outputs will be written. If True, HTML outputs
    will be written to a standard named file after a run, or give the exact filename
    of the file to be written."""

    title: str | None = None
    """Title of the HTML report.

    If this is None, the title will be the scenario name."""

    carrier_revenues: bool = True
    """Include carrier revenues in the HTML report."""

    carrier_total_bookings: bool = True
    """Include carrier total bookings in the HTML report."""

    carrier_revenue_distribution: bool = False
    """Include carrier revenue distribution in the HTML report."""

    carrier_load_factors: bool = True
    """Include carrier load factors in the HTML report."""

    carrier_yields: bool = True
    """Include carrier yields in the HTML report."""

    carrier_rasm: bool = True
    """Include carrier RASM in the HTML report."""

    carrier_local_share: bool = True
    """Include carrier local share in the HTML report."""

    fare_class_mix: bool = True
    """Include fare class mix in the HTML report.

    This figure is always by carrier."""

    bookings_by_timeframe: bool | list[str] = True
    """Include bookings by timeframe in the HTML report.

    If this is a list of strings, include only the specified carriers."""

    leg_load_factor_distribution: bool = True
    """Include leg load factor distribution in the HTML report."""

    bid_price_history: bool = True
    """Include bid price history in the HTML report."""

    displacement_history: bool = True
    """Include displacement history in the HTML report."""

    carrier_table: bool = True
    """Include carrier table in the HTML report."""

    segmentation_by_timeframe_table: bool = True
    """Include segmentation by timeframe table in the HTML report."""

    other: list[str | tuple[str, dict]] = []

    configs: list[str] = [
        "carriers",
        "rm_systems",
        "simulation_controls",
        "db",
        "outputs",
    ]
    """Include these configuration items in the HTML report."""

    metadata: bool = True
    """Include simulation run metadata in the HTML report."""

    def __bool__(self) -> bool:
        return bool(self.filename)

bid_price_history class-attribute instance-attribute

bid_price_history: bool = True

Include bid price history in the HTML report.

bookings_by_timeframe class-attribute instance-attribute

bookings_by_timeframe: bool | list[str] = True

Include bookings by timeframe in the HTML report.

If this is a list of strings, include only the specified carriers.

carrier_load_factors class-attribute instance-attribute

carrier_load_factors: bool = True

Include carrier load factors in the HTML report.

carrier_local_share class-attribute instance-attribute

carrier_local_share: bool = True

Include carrier local share in the HTML report.

carrier_rasm class-attribute instance-attribute

carrier_rasm: bool = True

Include carrier RASM in the HTML report.

carrier_revenue_distribution class-attribute instance-attribute

carrier_revenue_distribution: bool = False

Include carrier revenue distribution in the HTML report.

carrier_revenues class-attribute instance-attribute

carrier_revenues: bool = True

Include carrier revenues in the HTML report.

carrier_table class-attribute instance-attribute

carrier_table: bool = True

Include carrier table in the HTML report.

carrier_total_bookings class-attribute instance-attribute

carrier_total_bookings: bool = True

Include carrier total bookings in the HTML report.

carrier_yields class-attribute instance-attribute

carrier_yields: bool = True

Include carrier yields in the HTML report.

configs class-attribute instance-attribute

configs: list[str] = [
    "carriers",
    "rm_systems",
    "simulation_controls",
    "db",
    "outputs",
]

Include these configuration items in the HTML report.

displacement_history class-attribute instance-attribute

displacement_history: bool = True

Include displacement history in the HTML report.

fare_class_mix class-attribute instance-attribute

fare_class_mix: bool = True

Include fare class mix in the HTML report.

This figure is always by carrier.

filename class-attribute instance-attribute

filename: Path | bool | None = None

Write HTML outputs to this file after a run.

If this is None or False, no HTML outputs will be written. If True, HTML outputs will be written to a standard named file after a run, or give the exact filename of the file to be written.

leg_load_factor_distribution class-attribute instance-attribute

leg_load_factor_distribution: bool = True

Include leg load factor distribution in the HTML report.

metadata class-attribute instance-attribute

metadata: bool = True

Include simulation run metadata in the HTML report.

other class-attribute instance-attribute

other: list[str | tuple[str, dict]] = []

segmentation_by_timeframe_table class-attribute instance-attribute

segmentation_by_timeframe_table: bool = True

Include segmentation by timeframe table in the HTML report.

title class-attribute instance-attribute

title: str | None = None

Title of the HTML report.

If this is None, the title will be the scenario name.

__bool__

__bool__() -> bool
Source code in src/passengersim/config/outputs.py
def __bool__(self) -> bool:
    return bool(self.filename)

OutputConfig

Bases: PrettyModel

Source code in src/passengersim/config/outputs.py
class OutputConfig(PrettyModel, extra="forbid", validate_assignment=True):
    base_dir: pathlib.Path | None = None
    """Base directory for all output files.

    Whenever an output file is designated as a simple filename or a relative path,
    it will be relative to this directory.

    If not provided, the current working directory will be used.
    """

    filename_stem: str = "passengersim-output"
    """Default stem for all output files.

    If an output file is designated as `True` instead of giving an explicit
    filename, then this stem will be used with an appropriate file extension.
    """

    log_reports: bool = False
    """Write basic reports directly to the run log."""

    excel: bool | pathlib.Path | None = None
    """Write excel outputs to this file after a run."""

    reports: set[str | tuple[str, ...]] = set()
    """Reports to include.

    Database queries reports can be included here.  This is important for
    multiprocessing runs with in-memory databases, as database results will not
    be available after the database connection is closed in each subprocess.

    If this is a set containing only "*", all reports will be included; this
    may be computationally expensive.
    """

    html: HtmlOutputConfig = HtmlOutputConfig()
    """Configuration for HTML outputs."""

    pickle: bool | pathlib.Path | None = None
    """Write a pickle of the SimulationTables output to this file after a run."""

    sim_state: StateOutputConfig = StateOutputConfig()
    """Configuration for writing simulation dynamic state after each trial.

    In contrast with the *static* state, the *dynamic* state includes things that
    are created or change during a trial of the simulation, such as attribute counters,
    histories, and summaries.  The dynamic state is the information needed to recreate
    the Simulation object (beyond the contents of the Config) to facilitate various
    debugging and introspection.
    """

    disk: bool | pathlib.Path | None = True
    """Write the SimulationTables output to this file after a run.

    This will use pxsim format, an efficient binary file that allows "lazy" file
    loading.  If set to `True`, the file will be named with the same name as
    the HTML output file, except with the extension `.pxsim`, unless there is no
    HTML output file, in which case no file will written.
    """

    def _get_disk_filename(self) -> pathlib.Path | None:
        """Get the filename for the disk output.

        If the disk output is set to `True`, this will return the filename of
        the HTML output file with the extension `.pxsim`.  If there is no HTML
        output file, this will return None.
        """
        if self.disk is True and self.html.filename is not None:
            return self.html.filename.with_suffix(".pxsim")
        elif isinstance(self.disk, pathlib.Path):
            return self.disk
        else:
            return None

    def _resolve_output_filename(
        self,
        filename: str | pathlib.Path | bool,
        suffix: str | None = None,
        timestamp: str | float | time.struct_time | datetime.datetime | None = None,
        make_dirs: bool = False,
    ) -> pathlib.Path:
        """Resolve the output filename."""
        from passengersim.utils.filenaming import filename_with_timestamp

        if filename is False:
            raise ValueError("filename is False")
        if filename is None or filename is True:
            filename = self.filename_stem
        out_dir = self.base_dir if self.base_dir is not None else pathlib.Path.cwd()
        filename: pathlib.Path = pathlib.Path(filename)
        if suffix is not None:
            suffix: str = str(suffix)
            if not suffix.startswith("."):
                suffix = f".{suffix}"
            filename = filename.with_suffix(suffix)
        if timestamp:
            filename = filename_with_timestamp(filename, timestamp=timestamp)
        if make_dirs:
            filename.parent.mkdir(parents=True, exist_ok=True)
        if filename.is_absolute():
            return filename
        else:
            return out_dir / filename

    def get_output_filename(
        self,
        which: Literal["html", "disk", "pickle", "sim_state", "excel"],
        timestamp: str | float | time.struct_time | datetime.datetime | None = None,
        make_dirs: bool = False,
        **kwargs,
    ) -> pathlib.Path | None:
        if which == "html":
            if not self.html:
                return None
            return self._resolve_output_filename(
                self.html.filename or self.filename_stem,
                suffix=".html",
                timestamp=timestamp,
                make_dirs=make_dirs,
            )
        elif which == "disk":
            if not self.disk:
                return None
            return self._resolve_output_filename(
                self.disk if isinstance(self.disk, pathlib.Path) else self.filename_stem,
                suffix=".pxsim",
                timestamp=timestamp,
                make_dirs=make_dirs,
            )
        elif which == "pickle":
            if not self.pickle:
                return None
            return self._resolve_output_filename(
                self.pickle if isinstance(self.pickle, pathlib.Path) else self.filename_stem,
                suffix=".pkl",
                timestamp=timestamp,
                make_dirs=make_dirs,
            )
        elif which == "excel":
            if not self.excel:
                return None
            return self._resolve_output_filename(
                self.excel if isinstance(self.excel, pathlib.Path) else self.filename_stem,
                suffix=".xlsx",
                timestamp=timestamp,
                make_dirs=make_dirs,
            )
        elif which == "sim_state":
            if not self.sim_state.save:
                return None
            if "basename" not in kwargs:
                kwargs["basename"] = self.filename_stem
            return self._resolve_output_filename(
                self.sim_state._resolve_filename(**kwargs),
                suffix=".pax-state",
                timestamp=timestamp,
                make_dirs=make_dirs,
            )
        else:
            raise ValueError(f"Unknown output file format: {which}")

    def _write_no_files(self):
        """Write no files."""
        self.disk = False
        self.html.filename = False
        self.pickle = False
        self.excel = False
        self.sim_state.save = False

    # TODO what reports require what database items?
    # e.g. demand_to_come requires we store all `demand` not just demand_final

    @field_serializer("reports", when_used="always")
    def serialize_reports(self, reports: set[str | tuple[str, ...]]) -> list[str | tuple[str, ...]]:
        # return a sorted list, first simple strings then tuples
        return sorted(reports, key=lambda x: (isinstance(x, tuple), x))

base_dir class-attribute instance-attribute

base_dir: Path | None = None

Base directory for all output files.

Whenever an output file is designated as a simple filename or a relative path, it will be relative to this directory.

If not provided, the current working directory will be used.

disk class-attribute instance-attribute

disk: bool | Path | None = True

Write the SimulationTables output to this file after a run.

This will use pxsim format, an efficient binary file that allows "lazy" file loading. If set to True, the file will be named with the same name as the HTML output file, except with the extension .pxsim, unless there is no HTML output file, in which case no file will written.

excel class-attribute instance-attribute

excel: bool | Path | None = None

Write excel outputs to this file after a run.

filename_stem class-attribute instance-attribute

filename_stem: str = 'passengersim-output'

Default stem for all output files.

If an output file is designated as True instead of giving an explicit filename, then this stem will be used with an appropriate file extension.

html class-attribute instance-attribute

Configuration for HTML outputs.

log_reports class-attribute instance-attribute

log_reports: bool = False

Write basic reports directly to the run log.

pickle class-attribute instance-attribute

pickle: bool | Path | None = None

Write a pickle of the SimulationTables output to this file after a run.

reports class-attribute instance-attribute

reports: set[str | tuple[str, ...]] = set()

Reports to include.

Database queries reports can be included here. This is important for multiprocessing runs with in-memory databases, as database results will not be available after the database connection is closed in each subprocess.

If this is a set containing only "*", all reports will be included; this may be computationally expensive.

sim_state class-attribute instance-attribute

Configuration for writing simulation dynamic state after each trial.

In contrast with the static state, the dynamic state includes things that are created or change during a trial of the simulation, such as attribute counters, histories, and summaries. The dynamic state is the information needed to recreate the Simulation object (beyond the contents of the Config) to facilitate various debugging and introspection.

get_output_filename

get_output_filename(
    which: Literal[
        "html", "disk", "pickle", "sim_state", "excel"
    ],
    timestamp: str
    | float
    | struct_time
    | datetime
    | None = None,
    make_dirs: bool = False,
    **kwargs,
) -> Path | None
Source code in src/passengersim/config/outputs.py
def get_output_filename(
    self,
    which: Literal["html", "disk", "pickle", "sim_state", "excel"],
    timestamp: str | float | time.struct_time | datetime.datetime | None = None,
    make_dirs: bool = False,
    **kwargs,
) -> pathlib.Path | None:
    if which == "html":
        if not self.html:
            return None
        return self._resolve_output_filename(
            self.html.filename or self.filename_stem,
            suffix=".html",
            timestamp=timestamp,
            make_dirs=make_dirs,
        )
    elif which == "disk":
        if not self.disk:
            return None
        return self._resolve_output_filename(
            self.disk if isinstance(self.disk, pathlib.Path) else self.filename_stem,
            suffix=".pxsim",
            timestamp=timestamp,
            make_dirs=make_dirs,
        )
    elif which == "pickle":
        if not self.pickle:
            return None
        return self._resolve_output_filename(
            self.pickle if isinstance(self.pickle, pathlib.Path) else self.filename_stem,
            suffix=".pkl",
            timestamp=timestamp,
            make_dirs=make_dirs,
        )
    elif which == "excel":
        if not self.excel:
            return None
        return self._resolve_output_filename(
            self.excel if isinstance(self.excel, pathlib.Path) else self.filename_stem,
            suffix=".xlsx",
            timestamp=timestamp,
            make_dirs=make_dirs,
        )
    elif which == "sim_state":
        if not self.sim_state.save:
            return None
        if "basename" not in kwargs:
            kwargs["basename"] = self.filename_stem
        return self._resolve_output_filename(
            self.sim_state._resolve_filename(**kwargs),
            suffix=".pax-state",
            timestamp=timestamp,
            make_dirs=make_dirs,
        )
    else:
        raise ValueError(f"Unknown output file format: {which}")

serialize_reports

serialize_reports(
    reports: set[str | tuple[str, ...]],
) -> list[str | tuple[str, ...]]
Source code in src/passengersim/config/outputs.py
@field_serializer("reports", when_used="always")
def serialize_reports(self, reports: set[str | tuple[str, ...]]) -> list[str | tuple[str, ...]]:
    # return a sorted list, first simple strings then tuples
    return sorted(reports, key=lambda x: (isinstance(x, tuple), x))

StateOutputConfig

Bases: PrettyModel

Source code in src/passengersim/config/outputs.py
class StateOutputConfig(PrettyModel, extra="forbid", validate_assignment=True):
    save: bool = False
    """Save the state of the simulation after each trial."""

    filename: str = "[[basename]].pax-state/trial-[[trial]].pax-state"
    """Save the state of the simulation to this file after each trial.

    Accepts fields `basename` and `trial`, use double square brackets to
    insert these values.
    """

    include_trials: list[int] | None = None
    """Include trials when saving dynamic state.

    If left empty, all trials will be included.
    """

    def _resolve_filename(self, basename: str = "passengersim", trial: int = 999) -> str:
        return self.filename.replace("[[", "{").replace("]]", "}").format(basename=basename, trial=trial)

filename class-attribute instance-attribute

filename: str = (
    "[[basename]].pax-state/trial-[[trial]].pax-state"
)

Save the state of the simulation to this file after each trial.

Accepts fields basename and trial, use double square brackets to insert these values.

include_trials class-attribute instance-attribute

include_trials: list[int] | None = None

Include trials when saving dynamic state.

If left empty, all trials will be included.

save class-attribute instance-attribute

save: bool = False

Save the state of the simulation after each trial.