from __future__ import annotations
from typing import Dict
import matplotlib.axis
import numpy as np
import pandas as pd
from conflowgen.domain_models.data_types.mode_of_transport import ModeOfTransport
from conflowgen.previews.vehicle_capacity_exceeded_preview import VehicleCapacityExceededPreview
from conflowgen.reporting import AbstractReportWithMatplotlib
[docs]
class VehicleCapacityUtilizationOnOutboundJourneyPreviewReport(AbstractReportWithMatplotlib):
"""
This preview report takes the data structure as generated by
:class:`.VehicleCapacityExceededPreview`
and creates a comprehensible representation for the user, either as text or as a graph.
A similar report can be found at
:class:`.InboundAndOutboundVehicleCapacityPreviewReport`.
The visual and table are expected to approximately look like in the
`example InboundAndOutboundVehicleCapacityPreviewReport \
<notebooks/previews.ipynb#Inbound-And-Outbound-Vehicle-Capacity-Preview-Report>`_.
"""
report_description = """
This report previews the inbound and outbound traffic with a focus on up to which extend the vehicle capacities will
be exceeded. This is only an estimate, additional restrictions (such as the dwell time restrictions) might further
reduce the number of containers one vehicle can in fact pick up for its outbound journey.
"""
def __init__(self):
super().__init__()
self._df = None
self.preview = VehicleCapacityExceededPreview(
start_date=self.start_date,
end_date=self.end_date,
transportation_buffer=self.transportation_buffer
)
def hypothesize_with_mode_of_transport_distribution(
self,
mode_of_transport_distribution: Dict[ModeOfTransport, Dict[ModeOfTransport, float]]
):
self.preview.hypothesize_with_mode_of_transport_distribution(mode_of_transport_distribution)
[docs]
def get_report_as_text(
self, **kwargs
) -> str:
assert len(kwargs) == 0, f"No keyword arguments supported for {self.__class__.__name__}"
comparison = self._get_comparison()
# create string representation
report = "\n"
report += "vehicle type "
report += "maximum capacity (in TEU) "
report += "required capacity (in TEU) "
report += "exceeded "
report += "difference (in TEU)"
report += "\n"
for vehicle_type in self.order_of_vehicle_types_in_report:
vehicle_type_as_text = str(vehicle_type).replace("_", " ")
report += f"{vehicle_type_as_text:<17} "
(
container_capacity_to_pick_up,
maximum_capacity,
vehicle_type_capacity_is_exceeded
) = comparison[vehicle_type]
if not vehicle_type_capacity_is_exceeded:
difference = 0
else:
difference = container_capacity_to_pick_up - maximum_capacity
max_capacity_repr = -1 if np.isnan(maximum_capacity) else maximum_capacity
vehicle_type_capacity_is_exceeded_as_text = "yes" if vehicle_type_capacity_is_exceeded else "no"
report += f"{max_capacity_repr:>24.1f} "
report += f"{container_capacity_to_pick_up:>25.1f} "
report += f"{vehicle_type_capacity_is_exceeded_as_text:>9}"
report += f"{difference:>20.1f}"
report += "\n"
report += "(rounding errors might exist)\n"
return report
[docs]
def get_report_as_graph(self, **kwargs) -> matplotlib.axis.Axis:
"""
Returns:
The matplotlib axis of the bar chart.
"""
assert len(kwargs) == 0, f"No keyword arguments supported for {self.__class__.__name__}"
comparison = self._get_comparison()
self._df = pd.DataFrame.from_dict(comparison).T
self._df.columns = ["currently planned", "maximum", "exceeded"]
self._df.index = [str(i).replace("_", " ") for i in self._df.index]
ax = self._df.plot.barh()
ax.set_title("Capacity utilization on outbound journey")
ax.set_xlabel("Capacity (in TEU)")
return ax
def _get_comparison(self):
assert self.start_date is not None
assert self.end_date is not None
assert self.transportation_buffer is not None
self.preview.update(
start_date=self.start_date,
end_date=self.end_date,
transportation_buffer=self.transportation_buffer
)
# gather data
comparison = self.preview.compare()
return comparison