Source code for conflowgen.analyses.container_dwell_time_analysis_report

from __future__ import annotations

import datetime
import statistics
import typing  # noqa, pylint: disable=unused-import  # lgtm [py/unused-import]  # used in the docstring

import matplotlib.axis
import pandas as pd

from conflowgen.analyses.container_dwell_time_analysis import ContainerDwellTimeAnalysis
from conflowgen.reporting import AbstractReportWithMatplotlib
from conflowgen.reporting.no_data_plot import no_data_graph


[docs] class ContainerDwellTimeAnalysisReport(AbstractReportWithMatplotlib): """ This analysis report takes the data structure as generated by :class:`.ContainerDwellTimeAnalysis` and creates a comprehensible representation for the user, either as text or as a graph. The visual and table are expected to approximately look like in the `example ContainerDwellTimeAnalysisReport \ <notebooks/analyses.ipynb#Container-Dwell-Time-Analysis-Report>`_. """ report_description = """ Analyse the container dwell times. In the text version of the report, only the statistics are reported. In the visual version of the report, the dwell time distributions are plotted. """ def __init__(self): super().__init__() self.analysis = ContainerDwellTimeAnalysis()
[docs] def get_report_as_text(self, **kwargs) -> str: """ The report as a text is represented as a table suitable for logging. It uses a human-readable formatting style. For the exact interpretation of the parameter, check :meth:`.ContainerDwellTimeAnalysis.get_container_dwell_times`. Keyword Args: container_delivered_by_vehicle_type: One of ``"all"``, a collection of :class:`ModeOfTransport` enum values (as a list, set, or similar), or a single :class:`ModeOfTransport` enum value. container_picked_up_by_vehicle_type: One of ``"all"``, a collection of :class:`ModeOfTransport` enum values (as a list, set, or similar), or a single :class:`ModeOfTransport` enum value. storage_requirement: One of ``"all"``, a collection of :class:`StorageRequirement` enum values (as a list, set, or similar), or a single :class:`StorageRequirement` enum value. start_date (datetime.datetime): Only include containers that arrive after the given start time. Defaults to ``None``. end_date (datetime.datetime): Only include containers that depart before the given end time. Defaults to ``None``. Returns: The report in text format (possibly spanning over several lines). """ ( container_delivered_by_vehicle_type, container_dwell_times, container_picked_up_by_vehicle_type, storage_requirement ) = self._get_container_dwell_times(kwargs) container_dwell_times_in_hours = [ int(round(dwell_time.total_seconds() / 3600)) for dwell_time in container_dwell_times ] number_containers = len(container_dwell_times_in_hours) if number_containers: minimum_container_dwell_time = min(container_dwell_times_in_hours) maximum_container_dwell_timey = max(container_dwell_times_in_hours) average_container_dwell_time = statistics.mean(container_dwell_times_in_hours) stddev_container_dwell_time = statistics.stdev(container_dwell_times_in_hours) else: minimum_container_dwell_time = maximum_container_dwell_timey = average_container_dwell_time = 0 stddev_container_dwell_time = -1 # create string representation report = "\n" report += "container is delivered by vehicle type = " + self._get_vehicle_representation( container_delivered_by_vehicle_type) + "\n" report += "container picked up by vehicle type = " + self._get_vehicle_representation( container_picked_up_by_vehicle_type) + "\n" report += "storage requirement = " + self._get_storage_requirement_representation( storage_requirement) + "\n" report += f"number containers: {number_containers:>10}\n" report += " (reported in h)\n" report += f"minimum container dwell time: {minimum_container_dwell_time:>10.1f}\n" report += f"average container dwell time: {average_container_dwell_time:>10.1f}\n" report += f"maximum container dwell time: {maximum_container_dwell_timey:>10.1f}\n" report += f"standard deviation: {stddev_container_dwell_time:>10.1f}\n" report += "(rounding errors might exist)\n" return report
[docs] def get_report_as_graph(self, **kwargs) -> matplotlib.axis.Axis: """ The report as a graph is represented as a line graph using pandas. For the exact interpretation of the parameter, check :meth:`.ContainerDwellTimeAnalysis.get_container_dwell_times`. Keyword Args: container_delivered_by_vehicle_type: One of ``"all"``, a collection of :class:`ModeOfTransport` enum values (as a list, set, or similar), or a single :class:`ModeOfTransport` enum value. Defaults to ``all``. container_picked_up_by_vehicle_type: One of ``"all"``, a collection of :class:`ModeOfTransport` enum values (as a list, set, or similar), or a single :class:`ModeOfTransport` enum value. Defaults to ``all``. storage_requirement: One of ``"all"``, a collection of :class:`StorageRequirement` enum values (as a list, set, or similar), or a single :class:`StorageRequirement` enum value. Defaults to ``all``. start_date (datetime.datetime): Only include containers that arrive after the given start time. Defaults to ``None``. end_date (datetime.datetime): Only include containers that depart before the given end time. Defaults to ``None``. Returns: The matplotlib axis of the histogram """ ( container_delivered_by_vehicle_type, container_dwell_times, container_picked_up_by_vehicle_type, storage_requirement ) = self._get_container_dwell_times(kwargs) if len(container_dwell_times) == 0: fig, ax = no_data_graph() else: container_dwell_times_in_hours = [ int(round(dwell_time.total_seconds() / 3600)) for dwell_time in container_dwell_times ] series = pd.Series(list(container_dwell_times_in_hours)) ax = series.plot.hist() title = "" title += "container is delivered by vehicle type = " + self._get_vehicle_representation( container_delivered_by_vehicle_type) + "\n" title += "container picked up by vehicle type = " + self._get_vehicle_representation( container_picked_up_by_vehicle_type) + "\n" title += "storage requirement = " + self._get_storage_requirement_representation( storage_requirement) + "\n" ax.set_xlabel("Container Dwell Time (h)") ax.set_title(title) return ax
def _get_container_dwell_times(self, kwargs): container_delivered_by_vehicle_type = kwargs.pop("container_delivered_by_vehicle_type", "all") container_picked_up_by_vehicle_type = kwargs.pop("container_picked_up_by_vehicle_type", "all") storage_requirement = kwargs.pop("storage_requirement", "all") start_date = kwargs.pop("start_date", None) end_date = kwargs.pop("end_date", None) assert len(kwargs) == 0, f"Keyword(s) {list(kwargs.keys())} have not been processed" container_dwell_times: set[datetime.timedelta] = self.analysis.get_container_dwell_times( container_delivered_by_vehicle_type=container_delivered_by_vehicle_type, container_picked_up_by_vehicle_type=container_picked_up_by_vehicle_type, storage_requirement=storage_requirement, start_date=start_date, end_date=end_date ) return ( container_delivered_by_vehicle_type, container_dwell_times, container_picked_up_by_vehicle_type, storage_requirement )