Source code for conflowgen.analyses.truck_gate_throughput_analysis_report

from __future__ import annotations

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

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.axis

from conflowgen.analyses.truck_gate_throughput_analysis import TruckGateThroughputAnalysis
from conflowgen.reporting import AbstractReportWithMatplotlib
from conflowgen.reporting.no_data_plot import no_data_text


[docs] class TruckGateThroughputAnalysisReport(AbstractReportWithMatplotlib): """ This analysis report takes the data structure as generated by :class:`.TruckGateThroughputAnalysis` 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 TruckGateThroughputAnalysisReport \ <notebooks/analyses.ipynb#Truck-Gate-Throughput-Analysis-Report>`_. """ report_description = """ Analyze the trucks entering through the truck gate at each hour. Based on this, the required truck gate capacity in containers boxes can be deduced. In the text version of the report, only the statistics are reported. In the visual version of the report, the time series is plotted. """ plot_tile = "Analysis of truck gate throughput" def __init__(self): super().__init__() self.analysis = TruckGateThroughputAnalysis()
[docs] def get_report_as_text(self, **kwargs) -> str: """ Keyword Args: start_date (datetime.datetime): When to start recording end_date (datetime.datetime): When to end recording inbound (bool): Whether to check for trucks which deliver a container on their inbound journey outbound (bool): Whether to check for trucks which pick up a container on their outbound journey Returns: The report in text format. """ inbound = kwargs.pop("inbound", True) outbound = kwargs.pop("outbound", True) start_date = kwargs.pop("start_date", None) end_date = kwargs.pop("end_date", None) assert len(kwargs) == 0, f"The following keys have not been processed: {list(kwargs.keys())}" truck_gate_throughput = self.analysis.get_throughput_over_time( inbound=inbound, outbound=outbound, start_date=start_date, end_date=end_date ) if truck_gate_throughput: truck_gate_throughput_sequence = list(truck_gate_throughput.values()) maximum_truck_gate_throughput = max(truck_gate_throughput_sequence) average_truck_gate_throughput = statistics.mean(truck_gate_throughput_sequence) stddev_truck_gate_throughput = statistics.stdev(truck_gate_throughput_sequence) else: maximum_truck_gate_throughput = average_truck_gate_throughput = 0 stddev_truck_gate_throughput = -1 # create string representation report = "\n" report += " (reported in boxes)\n" report += f"maximum hourly truck gate throughput: {maximum_truck_gate_throughput:>10}\n" report += f"average hourly truck gate throughput: {average_truck_gate_throughput:>10.1f}\n" report += f"standard deviation: {stddev_truck_gate_throughput:>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. Keyword Args: start_date (datetime.datetime): When to start recording end_date (datetime.datetime): When to end recording inbound (bool): Whether to check for trucks which deliver a container on their inbound journey outbound (bool): Whether to check for trucks which pick up a container on their outbound journey ax (matplotlib.axis.Axis): Which matplotlib axis to plot on. Returns: The matplotlib axis of the plot over time. """ inbound = kwargs.pop("inbound", True) outbound = kwargs.pop("outbound", True) start_date = kwargs.pop("start_date", None) end_date = kwargs.pop("end_date", None) ax = kwargs.pop("ax", None) assert len(kwargs) == 0, f"The following keys have not been processed: {list(kwargs.keys())}" truck_gate_throughput = self.analysis.get_throughput_over_time( inbound=inbound, outbound=outbound, start_date=start_date, end_date=end_date ) if len(truck_gate_throughput) == 0: ax = no_data_text(ax) else: series = pd.Series(truck_gate_throughput) if ax is None: ax = series.plot() else: series.plot(ax=ax) plt.xticks(rotation=45) ax.set_xlabel("Date") ax.set_ylabel("Number of boxes (hourly count)") current_plot_title = self.plot_tile if inbound and not outbound: current_plot_title += " (inbound)" elif outbound and not inbound: current_plot_title += " (inbound)" else: current_plot_title += " (inbound and outbound)" ax.set_title(current_plot_title) return ax