API
Domain datatypes
- namedtuple ContainerFlowAdjustedToVehicleType(unchanged: float, train: float, barge: float, truck: float, deep_sea_vessel: float, feeder: float)
This is a mapping of all existing vehicle types and the additional entry ‘unchanged’ to the capacity that has been redirected to the respective type.
- enum ContainerLength(value)
The container length is one of the most important factors of how much space a container occupies. Here, the most common container sizes (neglecting height) are represented.
Valid values are as follows:
- twenty_feet = <ContainerLength.twenty_feet: 20>
A twenty-foot container
- forty_feet = <ContainerLength.forty_feet: 40>
A forty-foot container
- forty_five_feet = <ContainerLength.forty_five_feet: 45>
A forty-five-foot container
- other = <ContainerLength.other: -1>
Any other length usually does not fit into the standardized slots and handling processes.
The
Enum
and its members also have the following methods:- classmethod get_factor(container_length: ContainerLength) float
- Each container occupies a certain amount of space when stored.
This required space is measured in TEU.
Note
- CONTAINER_LENGTH_TO_OCCUPIED_TEU = {<ContainerLength.twenty_feet: 20>: 1, <ContainerLength.forty_feet: 40>: 2, <ContainerLength.forty_five_feet: 45>: 2.25, <ContainerLength.other: -1>: 2.5}
This is the translation table to specify the occupied storage space in TEU. For 20’, 40’, and 45’, the typical values are picked. The TEU factor for the value ‘other’ is chosen to be rather large because it is assumed to be difficult to find a proper storage position.
- Parameters
container_length – The length of the container
- Returns
The TEU factor of the container
- classmethod cast_element_type(text: str) ContainerLength | None
- Parameters
text – The text to parse
- Returns
The container length enum name if the cast was successful,
None
otherwise.
- namedtuple ContainersAndTEUContainerFlowPair(containers: Dict[ModeOfTransport, Dict[ModeOfTransport, float]], TEU: Dict[ModeOfTransport, Dict[ModeOfTransport, float]])
This is a pair of two container flows, i.e. the number of containers moving from A to B within a given time window. First, it is reported in containers which is important for reporting the efficiency at the interfaces, e.g. moves per hour for the ship-to-shore gantry cranes. Second, it is reported in TEU which is important for the yard capacity.
- Fields
containers (
Dict
[ModeOfTransport
,Dict
[ModeOfTransport
,float
]]) – Alias for field number 0TEU (
Dict
[ModeOfTransport
,Dict
[ModeOfTransport
,float
]]) – Alias for field number 1
- namedtuple HinterlandModalSplit(train_capacity: float, barge_capacity: float, truck_capacity: float)
This tuple keeps track of how much of the capacity that is either coming from or is destined to the hinterland is transported and by which vehicle type.
- enum ModeOfTransport(value)
The mode of transport describes the vehicle type of the vehicle which either drops off or picks up a container.
Valid values are as follows:
- truck = <ModeOfTransport.truck: 'truck'>
An external truck is sent by a freight forwarder
- train = <ModeOfTransport.train: 'train'>
A freight train is sent by a train operating company
- feeder = <ModeOfTransport.feeder: 'feeder'>
A feeder vessel is a rather small vessel sent by a ship operator and moves in the region
- deep_sea_vessel = <ModeOfTransport.deep_sea_vessel: 'deep_sea_vessel'>
A deep sea vessel is a rather large vessel sent by a ship operator and moves between distant regions, e.g. continents.
- barge = <ModeOfTransport.barge: 'barge'>
A barge is sent by an inland shipping operator
The
Enum
and its members also have the following methods:- classmethod get_scheduled_vehicles() List[ModeOfTransport]
- Returns
A list of vehicles that follow a schedule
- classmethod get_unscheduled_vehicles() List[ModeOfTransport]
- Returns
A list of vehicles that are created as they are needed to transport a container
- namedtuple OutboundUsedAndMaximumCapacity(used: Dict[ModeOfTransport, float], maximum: Dict[ModeOfTransport, float])
This tuple keeps track of how much each vehicle type transports on the outbound journey and what the maximum capacity is.
- Fields
used (
Dict
[ModeOfTransport
,float
]) – Alias for field number 0maximum (
Dict
[ModeOfTransport
,float
]) – Alias for field number 1
- namedtuple RequiredAndMaximumCapacityComparison(currently_planned: float, maximum: float, exceeded: bool)
This is a tuple that maintains three separate values for a given vehicle type. First, the currently planned capacity is recorded. Second, the maximum capacity is noted. If more capacity is requested than available, the exceeded flag is true, otherwise false.
- enum StorageRequirement(value)
A container is stored in different areas of the yard depending on its requirements.
Valid values are as follows:
- empty = <StorageRequirement.empty: 'empty'>
An empty container is stored in an empty container yard.
- standard = <StorageRequirement.standard: 'standard'>
A standard container is stored in the full container yard and makes up most of the containers passing through a container terminal.
- reefer = <StorageRequirement.reefer: 'reefer'>
A reefer container requires electricity (i.e., a reefer plug) to keep the inner temperature on a low level.
- dangerous_goods = <StorageRequirement.dangerous_goods: 'dangerous_goods'>
A dangerous goods container needs a specially prepared storage area so they do not constitute a major hazard to health and environment. These are also sometimes referred to as IMO containers.
- namedtuple TransshipmentAndHinterlandComparison(transshipment_capacity: float, hinterland_capacity: float)
This tuple keeps track of how much of the capacity is transshipment (i.e., dropped off and picked up by a vessel) and how much is hinterland (i.e., either dropped off or picked up by a vehicle that is not a vessel, e.g. a train or a truck).
- namedtuple CompleteVehicleIdentifier(mode_of_transport: ModeOfTransport, service_name: str, vehicle_name: str)
A vehicle identifier is a composition of the vehicle type, its service name, and the actual vehicle name
- Fields
mode_of_transport (
ModeOfTransport
) – Alias for field number 0service_name (
str
) – Alias for field number 1vehicle_name (
str
) – Alias for field number 2
Setting up ConFlowGen
- class DatabaseChooser(sqlite_databases_directory: Optional[str] = None)
This is a stateful library. For the purpose of reproducibility, the current input distributions are all stored in the database, likewise the generated vehicles etc. Thus, different scenarios can be stored in different SQLite databases.
- Parameters
sqlite_databases_directory – The DatabaseChooser opens one directory. All databases are saved to and load from this directory. It defaults to
<project root>/data/databases/
.
- close_current_connection() None
Close current connection, e.g. as a preparatory step to create a new SQLite database.
- create_new_sqlite_database(file_name: str, overwrite: bool = False, **seeder_options) None
All required tables are created and all input distributions are seeded with default values. These can be simply overwritten by the use-case specific distributions with the help of the API, e.g. the
ContainerLengthDistributionManager
,ContainerStorageRequirementDistributionManager
,ModeOfTransportDistributionManager
,TruckArrivalDistributionManager
, or similar. By default, no schedules and no vehicles exist.- Parameters
file_name – The file name of an SQLite database that will reside in
<project root>/data/databases/
overwrite – Whether to overwrite an existing database
**seeder_options – In case the database is seeded with default values, some variations exist that the user can choose from. The following options exist:
- Keyword Arguments
assume_tas (bool) – If a truck appointment system (TAS) is assumed, the corresponding truck arrival distribution is picked.
- setup_logger(logging_directory: Optional[str] = None, format_string: Optional[str] = None) Logger
This sets up the default logger with the name ‘conflowgen’. Several classes and functions use the same logger to inform the user about the current progress. This is just a convenience function, you can easily set up your own logger that uses the same name. See e.g. https://docs.python.org/3/howto/logging.html#configuring-logging for how to set up your own logger.
- Parameters
logging_directory – The path of the directory where to store logging files. Defaults to
<project root>/data/logs/
.format_string – The format string to use. See e.g. https://docs.python.org/3/library/logging.html#logrecord-attributes for how to create your own format string. Defaults to
%(asctime)s - %(name)s - %(levelname)s - %(message)s
.
- Returns
The set-up logger instance.
Setting input data
With the following classes, the schedules, input values and input distributions are set. These are all required for generating the synthetic data.
- class ContainerFlowGenerationManager
This manager provides the interface to set the properties (i.e., not the distributions that are handled elsewhere) and trigger the synthetic container flow generation. If not provided, for many of these values default values exist.
- container_flow_data_exists() bool
When an existing database is opened, pre-existing container flow data could already be stored inside. Invoking
ContainerFlowGenerationManager.generate()
again would reset that stored data. You might want to skip that set and just re-use the data already stored in the database.- Returns
Whether container flow data exists in the database.
- generate(overwrite: bool = True) None
Generate the synthetic container flow according to all the information stored in the database so far. This triggers a multistep procedure of generating vehicles and the containers which are delivered or picked up by the vehicles. More is described in the Section Data Generation Process. The invocation of this method overwrites any already existent data in the database. Consider checking for
ContainerFlowGenerationManager.container_flow_data_exists()
and skip invoking this method.
- get_properties() Dict[str, Union[str, date, float, int]]
- Returns
The properties of the container flow.
- set_properties(start_date: date, end_date: date, name: Optional[str] = None, minimum_dwell_time_of_import_containers_in_hours: Optional[int] = None, maximum_dwell_time_of_import_containers_in_hours: Optional[int] = None, minimum_dwell_time_of_export_containers_in_hours: Optional[int] = None, maximum_dwell_time_of_export_containers_in_hours: Optional[int] = None, minimum_dwell_time_of_transshipment_containers_in_hours: Optional[int] = None, maximum_dwell_time_of_transshipment_containers_in_hours: Optional[int] = None, transportation_buffer: Optional[float] = None) None
- Parameters
start_date – The earliest day any scheduled vehicle arrives. Trucks that drop off containers might arrive earlier though.
end_date – The latest day any scheduled vehicle arrives. Trucks that pick up containers might arrive later though.
name – The name of the generated synthetic container flow which helps to distinguish different scenarios.
minimum_dwell_time_of_import_containers_in_hours – No vehicle arrives earlier than this amount of hours to pick up an import container that has previously been dropped off.
maximum_dwell_time_of_import_containers_in_hours – No vehicles arrives later than this amount of hours after the previous vehicle which has dropped off the import container has arrived.
minimum_dwell_time_of_export_containers_in_hours – No vehicle arrives earlier than this amount of hours to pick up an export container that has previously been dropped off.
maximum_dwell_time_of_export_containers_in_hours – No vehicles arrives later than this amount of hours after the previous vehicle which has dropped off the export container has arrived.
minimum_dwell_time_of_transshipment_containers_in_hours – No vehicle arrives earlier than this amount of hours to pick up a transshipment container that has previously been dropped off.
maximum_dwell_time_of_transshipment_containers_in_hours – No vehicles arrives later than this amount of hours after the previous vehicle which has dropped off the transshipment container has arrived.
transportation_buffer – Determines how many percent more of the inbound journey capacity is used at most to transport containers on the outbound journey.
- class ContainerLengthDistributionManager
This manager provides the interface to set and get the container length distribution.
The default distribution is presented in the section Container Length Distribution.
- get_container_length_distribution() Dict[ContainerLength, float]
- Returns
The distribution of container lengths. Each length is assigned its frequency of showing up.
- set_container_length_distribution(container_lengths: Dict[ContainerLength, float]) None
Set the assumed global distribution of container lengths. This is applied to all vehicles that arrive at the terminal.
- Parameters
container_lengths – The distribution of container lengths and their corresponding frequency.
- class ContainerStorageRequirementDistributionManager
This is the interface to set and get the storage requirement distribution. It determines how many containers are selected to have a certain
StorageRequirement
.- get_storage_requirement_distribution() Dict[ContainerLength, Dict[StorageRequirement, float]]
- Returns
The distribution of storage requirements based on the length of the container.
- set_storage_requirement_distribution(storage_requirements: Dict[ContainerLength, Dict[StorageRequirement, float]]) None
Set the assumed global distribution of container storage requirements. This is applied to all containers passing through the terminal.
- Parameters
storage_requirements – The distribution of storage requirements depending on the container length.
- class ContainerWeightDistributionManager
This is the interface to set and get the container weight distribution. With the help of this distribution, the weight of each container is drawn. The default distribution is presented in the section Container Weight Distribution.
- class ModeOfTransportDistributionManager
This is the interface to set and get the distribution that controls from which vehicle containers are transshipped to which other type of vehicle.
- get_mode_of_transport_distribution() Dict[ModeOfTransport, Dict[ModeOfTransport, float]]
- Returns
The distribution of mode of transports dependent on the vehicle the container is delivered by. If a container is delivered by a vehicle of type
<first-key>
, the floating point number describes the fraction that the container is later picked up by vehicle of type<second-key>
.
- set_mode_of_transport_distribution(distribution: Dict[ModeOfTransport, Dict[ModeOfTransport, float]]) None
- Parameters
distribution – If a container is delivered by a vehicle of type
<first-key>
, the floating point number describes the fraction that the container is later picked up by vehicle of type<second-key>
.
- class PortCallManager
This manager provides the interface to create schedules for services that periodically call the container terminal, e.g. ships of any size and trains. This explicitly does not cover the trucks which arrive according to a probability distribution set at
TruckArrivalDistributionManager
.- add_large_scheduled_vehicle(vehicle_type: ModeOfTransport, service_name: str, vehicle_arrives_at: date, vehicle_arrives_at_time: time, average_vehicle_capacity: int, average_moved_capacity: int, next_destinations: Optional[List[Tuple[str, float]]] = None, vehicle_arrives_every_k_days: Optional[int] = None) None
Add the schedule of a ship of any size or a train. The concrete vehicle instances are automatically generated when
ContainerFlowGenerationManager.generate()
is invoked.- Parameters
vehicle_type – One of
ModeOfTransport.deep_sea_vessel
,ModeOfTransport.feeder
,ModeOfTransport.barge
, orModeOfTransport.train
service_name – The name of the service, i.e. the shipping line or rail freight line
vehicle_arrives_at – A date the service would arrive at the terminal. This can e.g. point at the week day for weekly services. In any case, this is combined with the parameter
vehicle_arrives_every_k_days
and only arrivals within the time scope betweenstart_date
andend_date
are considered.vehicle_arrives_at_time – A time of the day (between 00:00 and 23:59).
average_vehicle_capacity – Number of TEU that can be transported with the vehicle at most. The number of moved containers can never exceed this number, no matter what the value for the
transportation_buffer
is set to.average_moved_capacity –
The average moved capacity describes the number of TEU which the vehicle delivers to the terminal on its inbound journey. When summing up the TEU factors of each of the loaded containers on the inbound journey, this value is never exceeded but closely approximated. For the outbound journey, the containers are assigned depending on the distribution kept in
ModeOfTransportDistributionManager
. The maximum number of containers in TEU on the outbound journey of the vehicle is bound by\[min( \text{average_moved_capacity} \cdot \text{transportation_buffer},\text{average_vehicle_capacity} )\]If you have calibrated the aforementioned distribution accordingly, the actual number of containers on the outbound journey in TEU should be on average the same as on the inbound journey. In that case, the vehicle moves
average_moved_capacity
number of containers in TEU on its inbound journey and the same number of containers in TEU again on its outbound journey.next_destinations – Pairs of destination and frequency of the destination being chosen.
vehicle_arrives_every_k_days – Defaults to weekly services (arrival every 7 days). Other frequencies are possible as well. In the special case of
-1
, only a single arrival is scheduled for dayvehicle_arrives_at
as long as the specified date lies withinstart_date
andend_date
. This arrival is only part of the generated container flow if that arrival lies betweenstart_date
andend_date
.
- has_schedule(service_name: str, vehicle_type: ModeOfTransport) bool
- Parameters
service_name – The name of the service which moves to a schedule that is sought for.
vehicle_type – The mode of transport to restrict the search to.
- Returns
Whether the requested schedule already exist in the database.
- class TruckArrivalDistributionManager
This manager provides the interface to set and get the weekly arrival rates of trucks. When the truck arrival time is drawn from this distribution, first a slice for the minimum and maximum dwell time is created and the arrival time of the truck is drawn from that period. All other vehicles are created based on the schedule they adhere to with the help of the
PortCallManager
- get_truck_arrival_distribution() Dict[int, float]
Each key represents the hour in the week and each value represents the probability of a truck to arrive between that hour and the start of the next time slot (the successor is the nearest key larger than the current key).
- Returns
The truck arrival distribution.
- set_truck_arrival_distribution(distribution: Dict[int, float]) None
- Parameters
distribution – The truck arrival distribution. Each key represents the hour in the week and each value represents the probability of a truck to arrive between that hour and the start of the next time slot (the successor is the nearest key larger than the current key).
Getting previews
- class ContainerFlowByVehicleTypePreview(start_date: date, end_date: date, transportation_buffer: float)
This preview tells the user how many containers are planned to be transshipped between which types of vehicles.
The preview returns a data structure that can be used for generating reports (e.g., in text or as a figure) as it is the case with
ContainerFlowByVehicleTypePreviewReport
. The preview is intended to provide a first estimate before running the expensiveContainerFlowGenerationManager.generate()
method. The preview does not consider all restrictions (such as container dwell times in combination with the schedules) into consideration, thus later deviations might exist.- Parameters
start_date – The earliest day to consider when checking the vehicles that move according to schedules
end_date – The latest day to consider when checking the vehicles that move according to schedules
transportation_buffer – The fraction of how much more a vehicle takes with it on an outbound journey compared to an inbound journey as long as the total vehicle capacity is not exceeded.
- get_inbound_to_outbound_flow() Dict[ModeOfTransport, Dict[ModeOfTransport, float]]
The estimated flow of containers from vehicles on their inbound journey to vehicles on their outbound journey based on the mode of transport distribution.
- Returns
A flow from vehicle type A to vehicle type B estimated in TEU.
- hypothesize_with_mode_of_transport_distribution(mode_of_transport_distribution: Dict[ModeOfTransport, Dict[ModeOfTransport, float]])
This allows to see the effect of different mode of transport distributions on this preview.
- Parameters
mode_of_transport_distribution – A mode of transport distribution to try out
- class ContainerFlowByVehicleTypePreviewReport
This preview report takes the data structure as generated by
ContainerFlowByVehicleTypePreview
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 ContainerFlowByVehicleTypePreviewReport.- get_report_as_graph() object
The container flow is represented by a Sankey diagram.
- Returns
The plotly figure of the Sankey diagram.
Note
At the time of writing, plotly comes with some shortcomings.
Sorting the labels on either the left or right side without recalculating the height of each bar is not possible, see https://github.com/plotly/plotly.py/issues/1732.
Empty nodes require special handling, see https://github.com/plotly/plotly.py/issues/3003 and the coordinates need to be \(0 < x,y < 1\) (no equals!), see https://github.com/plotly/plotly.py/issues/3002.
However, it seems to be the best available library for plotting Sankey diagrams that can be visualized e.g. in a Jupyter Notebook.
- class InboundAndOutboundVehicleCapacityPreview(start_date: date, end_date: date, transportation_buffer: float)
This preview examines how much the inbound vehicles deliver to the terminal and how it is redistributed to the outbound journeys of the other vehicles according to the mode of transport distribution. This pre-checks whether the transport capacity of the vehicles will be exceeded. In such case, the input schedules and distributions should be further refined before generating a container flow.
The preview returns a data structure that can be used for generating reports (e.g., in text or as a figure) as it is the case with
InboundAndOutboundVehicleCapacityPreviewReport
. The preview is intended to provide a first estimate before running the expensiveContainerFlowGenerationManager.generate()
method. The preview does not consider all restrictions (such as container dwell times in combination with the schedules) into consideration, thus later deviations might exist.- Parameters
start_date – The earliest day to consider when checking the vehicles that move according to schedules
end_date – The latest day to consider when checking the vehicles that move according to schedules
transportation_buffer – The fraction of how much more a vehicle takes with it on an outbound journey compared to an inbound journey as long as the total vehicle capacity is not exceeded.
- get_inbound_capacity_of_vehicles() Dict[ModeOfTransport, float]
For the inbound capacity, first vehicles that adhere to a schedule are considered. Trucks, which are created depending on the outbound distribution, are created based on the assumptions of the further container flow generation process.
- get_outbound_capacity_of_vehicles() OutboundUsedAndMaximumCapacity
For the outbound capacity, both the used outbound capacity (estimated) and the maximum outbound capacity is reported. If a vehicle type reaches the maximum outbound capacity, this means that containers need to be redistributed to other vehicle types due to a lack of capacity.
- hypothesize_with_mode_of_transport_distribution(mode_of_transport_distribution: Dict[ModeOfTransport, Dict[ModeOfTransport, float]])
This allows to see the effect of different mode of transport distributions on this preview.
- Parameters
mode_of_transport_distribution – A mode of transport distribution to try out
- class InboundAndOutboundVehicleCapacityPreviewReport
This preview report takes the data structure as generated by
InboundAndOutboundVehicleCapacityPreview
and creates a comprehensible representation for the user, either as text or as a graph. A similar report can be found atVehicleCapacityExceededPreviewReport
. The visual and table are expected to approximately look like in the example InboundAndOutboundVehicleCapacityPreviewReport.
- class ModalSplitPreview(start_date: date, end_date: date, transportation_buffer: float)
This preview examines the inbound and/or outbound journeys and estimates the modal split. This is separated into two different aspects. First, the transshipment share is indicated. For the hinterland, the modal split is reported.
The preview returns a data structure that can be used for generating reports (e.g., in text or as a figure) as it is the case with
ModalSplitPreviewReport
. The preview is intended to provide a first estimate before running the expensiveContainerFlowGenerationManager.generate()
method. The preview does not consider all restrictions (such as container dwell times in combination with the schedules) into consideration, thus later deviations might exist.- Parameters
start_date – The earliest day to consider when checking the vehicles that move according to schedules
end_date – The latest day to consider when checking the vehicles that move according to schedules
transportation_buffer – The fraction of how much more a vehicle takes with it on an outbound journey compared to an inbound journey as long as the total vehicle capacity is not exceeded.
- get_modal_split_for_hinterland(inbound: bool, outbound: bool) HinterlandModalSplit
- Parameters
inbound – Whether to account for inbound journeys
outbound – Whether to account for outbound journeys
- Returns
The estimated modal split for the hinterland
- Returns
The amount of containers in TEU dedicated for or coming from the hinterland versus the amount of containers in TEU that are transshipped.
- hypothesize_with_mode_of_transport_distribution(mode_of_transport_distribution: Dict[ModeOfTransport, Dict[ModeOfTransport, float]])
This allows to see the effect of different mode of transport distributions on this preview.
- Parameters
mode_of_transport_distribution – A mode of transport distribution to try out
- class ModalSplitPreviewReport
This preview report takes the data structure as generated by
ModalSplitPreview
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 ModalSplitPreviewReport.
- run_all_previews(as_text: bool = True, as_graph: bool = False, display_text_func: Optional[Callable] = None, display_in_markup_language: Optional[Union[DisplayAsMarkupLanguage, str]] = None, static_graphs: bool = False) None
Runs all preview analyses in sequence. This is just a convenience function to ensure that all reports are presented. The text output is logged to the logger with the name ‘conflowgen’ by default. See
setup_logger()
for more details.- Parameters
as_text – Whether to get the reports as text and log them.
as_graph – Whether to display the reports as graphs (visualizations will pop up).
display_text_func – The function to use to display the text. Defaults to
logger.info()
.display_in_markup_language – The markup language to use. Currently, the options ‘markdown’ and ‘plaintext’ exist. Defaults to
DisplayAsPlainText
(same as ‘plaintext’), users can provide their own approach withDisplayAsMarkupLanguage
.static_graphs – Whether the graphs should be static. Plotly has some nice interactive options that are currently not supported inside some websites such as the HTML version of the documentation. In such cases, the static version of the plots is used.
- class VehicleCapacityExceededPreview(start_date: date, end_date: date, transportation_buffer: float)
The preview examines the outbound traffic and checks if the intended transportation demands can be satisfied by the existing transport capacities (per vehicle type).
The preview returns a data structure that can be used for generating reports (e.g., in text or as a figure) as it is the case with
VehicleCapacityExceededPreviewReport
. The preview is intended to provide a first estimate before runningContainerFlowGenerationManager.generate()
which is time-consuming. The preview does not consider all restrictions (such as container dwell times in combination with the schedules) into consideration, thus later deviations might exist.- Parameters
start_date – The earliest day to consider when checking the vehicles that move according to schedules
end_date – The latest day to consider when checking the vehicles that move according to schedules
transportation_buffer – The fraction of how much more a vehicle takes with it on an outbound journey compared to an inbound journey as long as the total vehicle capacity is not exceeded.
- compare() Dict[ModeOfTransport, RequiredAndMaximumCapacityComparison]
Compare the required capacity of vehicles on their outbound journey to transport all containers and the maximum capacity of the vehicles on their outbound journey. If the maximum capacity of the vehicles is exceeded, this mismatch is indicated (per vehicle type, in TEU).
- hypothesize_with_mode_of_transport_distribution(mode_of_transport_distribution: Dict[ModeOfTransport, Dict[ModeOfTransport, float]])
This allows to see the effect of different mode of transport distributions on this preview.
- Parameters
mode_of_transport_distribution – A mode of transport distribution to try out
- class VehicleCapacityExceededPreviewReport
This preview report takes the data structure as generated by
VehicleCapacityExceededPreview
and creates a comprehensible representation for the user, either as text or as a graph. A similar report can be found atInboundAndOutboundVehicleCapacityPreviewReport
. The visual and table are expected to approximately look like in the example InboundAndOutboundVehicleCapacityPreviewReport.
Getting analyses
- class ContainerFlowAdjustmentByVehicleTypeAnalysis(transportation_buffer: Optional[float] = None)
This analysis can be run after the synthetic data has been generated. The analysis returns a data structure that can be used for generating reports (e.g., in text or as a figure) as it is the case with
ContainerFlowAdjustmentByVehicleTypeAnalysisReport
.- Parameters
transportation_buffer – The buffer, e.g. 0.2 means that 20% more containers (in TEU) can be put on a vessel compared to the amount of containers it had on its inbound journey - as long as the total vehicle capacity would not be exceeded.
- static get_initial_to_adjusted_outbound_flow() ContainersAndTEUContainerFlowPair
When containers are generated, in order to obey the maximum dwell time, the vehicle type that is used for onward transportation might change. The initial outbound vehicle type is the vehicle type that is drawn randomly for a container at the time of generation. The adjusted vehicle type is the vehicle type that is drawn in case no vehicle of the initial outbound vehicle type is left within the maximum dwell time.
- Returns
The data structure describes how often an initial outbound vehicle type had to be adjusted with which other vehicle type.
- class ContainerFlowAdjustmentByVehicleTypeAnalysisReport
This analysis report takes the data structure as generated by
ContainerFlowAdjustmentByVehicleTypeAnalysis
and creates a comprehensible representation for the user, either as text or as a graph.- get_report_as_graph() object
The container flow is represented by a Sankey diagram.
Note
At the time of writing, plotly comes with some shortcomings.
Sorting the labels on either the left or right side without recalculating the height of each bar is not possible, see https://github.com/plotly/plotly.py/issues/1732.
Empty nodes require special handling, see https://github.com/plotly/plotly.py/issues/3003 and the coordinates need to be \(0 < x,y < 1\) (no equals!), see https://github.com/plotly/plotly.py/issues/3002.
However, it seems to be the best available library for plotting Sankey diagrams that can be visualized e.g. in a Jupyter Notebook.
- Returns
The plotly figure of the Sankey diagram.
- class ContainerFlowAdjustmentByVehicleTypeAnalysisSummary(transportation_buffer: Optional[float] = None)
This analysis summary can be run after the synthetic data has been generated. The analysis summary returns a data structure that can be used for generating reports (e.g., in text or as a figure) as it is the case with
ContainerFlowAdjustmentByVehicleTypeAnalysisSummaryReport
.- Parameters
transportation_buffer – The buffer, e.g. 0.2 means that 20% more containers (in TEU) can be put on a vessel compared to the amount of containers it had on its inbound journey - as long as the total vehicle capacity would not be exceeded.
- get_summary() ContainerFlowAdjustedToVehicleType
Under certain circumstances (as explained in
ContainerFlowAdjustmentByVehicleTypeAnalysis.get_initial_to_adjusted_outbound_flow()
), the containers must change the vehicle they leave the yard with. Thus, the question remains how often this has been the case and which vehicles were the primary target for this redirected traffic? The capacity is expressed in TEU.
- class ContainerFlowAdjustmentByVehicleTypeAnalysisSummaryReport
This analysis report takes the data structure as generated by
ContainerFlowAdjustmentByVehicleTypeAnalysisSummary
and creates a comprehensible representation for the user, either as text or as a graph.
- class ContainerFlowByVehicleTypeAnalysis(transportation_buffer: Optional[float] = None)
This analysis can be run after the synthetic data has been generated. The analysis returns a data structure that can be used for generating reports (e.g., in text or as a figure) as it is the case with
ContainerFlowByVehicleTypeAnalysisReport
.- Parameters
transportation_buffer – The buffer, e.g. 0.2 means that 20% more containers (in TEU) can be put on a vessel compared to the amount of containers it had on its inbound journey - as long as the total vehicle capacity would not be exceeded.
- static get_inbound_to_outbound_flow(as_teu: bool = True) Dict[ModeOfTransport, Dict[ModeOfTransport, float]]
This is the overview of the generated inbound to outbound container flow by vehicle type.
- class ContainerFlowByVehicleTypeAnalysisReport
This analysis report takes the data structure as generated by
ContainerFlowByVehicleTypeAnalysis
and creates a comprehensible representation for the user, either as text or as a graph.- get_report_as_graph() object
The container flow is represented by a Sankey diagram.
- Returns
The plotly figure of the Sankey diagram.
Note
At the time of writing, plotly comes with some shortcomings.
Sorting the labels on either the left or right side without recalculating the height of each bar is not possible, see https://github.com/plotly/plotly.py/issues/1732.
Empty nodes require special handling, see https://github.com/plotly/plotly.py/issues/3003 and the coordinates need to be \(0 < x,y < 1\) (no equals!), see https://github.com/plotly/plotly.py/issues/3002.
However, it seems to be the best available library for plotting Sankey diagrams that can be visualized e.g. in a Jupyter Notebook.
- class InboundAndOutboundVehicleCapacityAnalysis(transportation_buffer: float)
This analysis can be run after the synthetic data has been generated. The analysis returns a data structure that can be used for generating reports (e.g., in text or as a figure) as it is the case with
InboundAndOutboundVehicleCapacityAnalysisReport
.- Parameters
transportation_buffer – The buffer, e.g. 0.2 means that 20% more containers (in TEU) can be put on a vessel compared to the amount of containers it had on its inbound journey - as long as the total vehicle capacity would not be exceeded.
- static get_inbound_capacity_of_vehicles() Dict[ModeOfTransport, float]
This is the used capacity of all vehicles separated by vehicle type on their inbound journey in TEU.
- get_outbound_capacity_of_vehicles() OutboundUsedAndMaximumCapacity
This is the used and the maximum capacity of all vehicles separated by vehicle type on their outbound journey in TEU. If for a vehicle type, the used capacity is very close to the maximum capacity, you might want to reconsider the mode of transport distribution. See
ModeOfTransportDistributionManager
for further details.
- class InboundAndOutboundVehicleCapacityAnalysisReport
This analysis report takes the data structure as generated by
InboundAndOutboundVehicleCapacityAnalysis
and creates a comprehensible representation for the user, either as text or as a graph.
- class InboundToOutboundVehicleCapacityUtilizationAnalysis(transportation_buffer: float)
This analysis can be run after the synthetic data has been generated. The analysis returns a data structure that can be used for generating reports (e.g., in text or as a figure) as it is the case with
InboundToOutboundCapacityUtilizationAnalysisReport
.- Parameters
transportation_buffer – The buffer, e.g. 0.2 means that 20% more containers (in TEU) can be put on a vessel compared to the amount of containers it had on its inbound journey - as long as the total vehicle capacity would not be exceeded.
- static get_inbound_and_outbound_capacity_of_each_vehicle(vehicle_type='all') Dict[CompleteVehicleIdentifier, Tuple[float, float]]
- Parameters
vehicle_type – Either
"all"
, a single vehicle of typeModeOfTransport
or a whole collection of vehicle types, e.g. passed as alist
orset
. Only the vehicles that correspond to the provided vehicle type(s) are considered in the analysis.- Returns
The transported containers of each vehicle on their inbound and outbound journey in TEU.
- class InboundToOutboundVehicleCapacityUtilizationAnalysisReport
This analysis report takes the data structure as generated by
InboundToOutboundCapacityUtilizationAnalysis
and creates a comprehensible representation for the user, either as text or as a graph.- get_report_as_graph(**kwargs) object
The report as a graph is represented as a scatter plot using pandas.
- Keyword Arguments
plot_type – Either “absolute”, “relative”, or “both”. Defaults to “both”.
vehicle_type – Either
"all"
, a single vehicle of typeModeOfTransport
or a whole collection of vehicle types, e.g. passed as alist
orset
. For the exact interpretation of the parameter, checkInboundToOutboundVehicleCapacityUtilizationAnalysis
.
- Returns
The matplotlib figure
- get_report_as_text(**kwargs) str
The report as a text is represented as a table suitable for logging. It uses a human-readable formatting style.
- Keyword Arguments
vehicle_type – Either
"all"
, a single vehicle of typeModeOfTransport
or a whole collection of vehicle types, e.g. passed as alist
orset
. For the exact interpretation of the parameter, checkInboundToOutboundVehicleCapacityUtilizationAnalysis
.- Returns
The report in text format (possibly spanning over several lines).
- class ModalSplitAnalysis
This analysis can be run after the synthetic data has been generated. The analysis returns a data structure that can be used for generating reports (e.g., in text or as a figure) as it is the case with
ModalSplitAnalysisReport
.- Parameters
transportation_buffer – The buffer, e.g. 0.2 means that 20% more containers (in TEU) can be put on a vessel compared to the amount of containers it had on its inbound journey - as long as the total vehicle capacity would not be exceeded.
- get_modal_split_for_hinterland(inbound: bool, outbound: bool) HinterlandModalSplit
- Parameters
inbound – Whether to account for inbound journeys
outbound – Whether to account for outbound journeys
- Returns
The modal split for the hinterland as generated.
- get_transshipment_and_hinterland_fraction() TransshipmentAndHinterlandComparison
- Returns
The amount of containers in TEU dedicated for or coming from the hinterland versus the amount of containers in TEU that are transshipped.
- class ModalSplitAnalysisReport
This analysis report takes the data structure as generated by
ModalSplitAnalysis
and creates a comprehensible representation for the user, either as text or as a graph.
- class QuaySideThroughputAnalysis(transportation_buffer: Optional[float] = None)
This analysis can be run after the synthetic data has been generated. The analysis returns a data structure that can be used for generating reports (e.g., in text or as a figure) as it is the case with
QuaySideThroughputAnalysisReport
.- Parameters
transportation_buffer – The buffer, e.g. 0.2 means that 20% more containers (in TEU) can be put on a vessel compared to the amount of containers it had on its inbound journey - as long as the total vehicle capacity would not be exceeded.
- classmethod get_throughput_over_time(inbound: bool = True, outbound: bool = True) Dict[date, float]
For each week, the containers crossing the quay are checked. Based on this, the required quay capacity in boxes can be deduced - it is the maximum of these values (based on all the assumptions, in reality an additional buffer might be reasonable to add).
The rather coarse time window is due to the fact that the discharging and loading process are not modelled. At this stage, as a simplification all containers arriving with a vessel are discharged at once and all containers departing with a vessel are loaded at once. This is smoothed by the larger time window.
- Parameters
inbound – Whether to check for vessels which deliver a container on their inbound journey
outbound – Whether to check for vessels which pick up a container on their outbound journey
- class QuaySideThroughputAnalysisReport
This analysis report takes the data structure as generated by
QuaySideThroughputAnalysis
and creates a comprehensible representation for the user, either as text or as a graph.
- run_all_analyses(as_text: bool = True, as_graph: bool = False, display_text_func: Optional[Callable] = None, display_in_markup_language: Optional[Union[DisplayAsMarkupLanguage, str]] = None, static_graphs: bool = False) None
Runs all post-hoc analyses in sequence. This is just a convenience function to ensure that all reports are presented. The text output is logged to the logger with the name ‘conflowgen’ by default.. See
setup_logger()
for more details.- Parameters
as_text – Whether to get the reports as text and log them
as_graph – Whether to display the reports as graphs (visualizations will pop up)
display_text_func – The function to use to display the text. Defaults to
logger.info()
.display_in_markup_language – The markup language to use. Currently, the options ‘markdown’ and ‘plaintext’ exist. Defaults to
DisplayAsPlainText
(same as ‘plaintext’), users can provide their own approach withDisplayAsMarkupLanguage
.static_graphs – Whether the graphs should be static. Plotly has some nice interactive options that are currently not supported inside some websites such as the HTML version of the documentation. In such cases, the static version of the plots is used.
- class TruckGateThroughputAnalysis(transportation_buffer: Optional[float] = None)
This analysis can be run after the synthetic data has been generated. The analysis returns a data structure that can be used for generating reports (e.g., in text or as a figure) as it is the case with
TruckGateThroughputAnalysisReport
.- Parameters
transportation_buffer – The buffer, e.g. 0.2 means that 20% more containers (in TEU) can be put on a vessel compared to the amount of containers it had on its inbound journey - as long as the total vehicle capacity would not be exceeded.
- classmethod get_throughput_over_time(inbound: bool = True, outbound: bool = True) Dict[datetime, float]
For each hour, the trucks entering through the truck gate are checked. Based on this, the required truck gate capacity in boxes can be deduced.
- Parameters
inbound – Whether to check for trucks which deliver a container on their inbound journey
outbound – Whether to check for trucks which pick up a container on their outbound journey
- class TruckGateThroughputAnalysisReport
This analysis report takes the data structure as generated by
TruckGateThroughputAnalysis
and creates a comprehensible representation for the user, either as text or as a graph.
- class YardCapacityAnalysis(transportation_buffer: Optional[float] = None)
This analysis can be run after the synthetic data has been generated. The analysis returns a data structure that can be used for generating reports (e.g., in text or as a figure) as it is the case with
YardCapacityAnalysisReport
.- Parameters
transportation_buffer – The buffer, e.g. 0.2 means that 20% more containers (in TEU) can be put on a vessel compared to the amount of containers it had on its inbound journey - as long as the total vehicle capacity would not be exceeded.
- static get_used_yard_capacity_over_time(storage_requirement: Union[str, Collection, StorageRequirement] = 'all') Dict[datetime, float]
For each hour, the containers entering and leaving the yard are checked. Based on this, the required yard capacity in TEU can be deduced - it is simply the maximum of these values. In addition, with the parameter
storage_requirement
the yard capacity can be filtered, e.g. to only include standard containers, empty containers, or any other kind of subset.Please be aware that this method slightly overestimates the required capacity. If one container leaves the yard at the beginning of the respective time window and another container enters the yard at the end of the same time window, still the TEU equivalence of both containers is recorded as the required yard capacity. Obviously the entering container could use the same slot as the container which entered later. This minor inaccuracy might be of little importance because no yard should be planned that tight. The benefit is that it further allows a faster computation.
- Parameters
storage_requirement – One of
"all"
, a collection ofStorageRequirement
enum values (as a list, set, or similar), or a singleStorageRequirement
enum value.- Returns
A series of the used yard capacity in TEU over the time.
- class YardCapacityAnalysisReport
This analysis report takes the data structure as generated by
YardCapacityAnalysis
and creates a comprehensible representation for the user, either as text or as a graph.- get_report_as_graph(**kwargs) object
The report as a graph is represented as a line graph using pandas.
- Keyword Arguments
storage_requirement – Either a single storage requirement of type
StorageRequirement
or a whole collection of them e.g. passed as alist
orset
. For the exact interpretation of the parameter, checkYardCapacityAnalysis.get_used_yard_capacity_over_time()
.- Returns
The matplotlib axis of the bar chart.
- get_report_as_text(**kwargs) str
The report as a text is represented as a table suitable for logging. It uses a human-readable formatting style.
- Keyword Arguments
storage_requirement – Either a single storage requirement of type
StorageRequirement
or a whole collection of them e.g. passed as alist
orset
. For the exact interpretation of the parameter, checkYardCapacityAnalysis.get_used_yard_capacity_over_time()
.- Returns
The report in text format (possibly spanning over several lines).
Working with reports
When working with run_all_previews()
or run_all_analyses()
, there is some common functionality.
If you wish to add another markup language besides plaintext and markdown for these two lists of reports,
you can define them here and pass them as parameters to the aforementioned functions.
- class DisplayAsMarkdown(display_markdown_func: Callable)
With this style, the output is set in Markdown. This is e.g. helpful when showing the output in Jupyter Notebooks.
- display_explanation(text: str)
- Parameters
text – The text of an explanatory text (shown in normal font, wrapped if required). Different paragraphs are separated by repeated invocations of this method.
- class DisplayAsMarkupLanguage
This is the abstract class new markup language definitions can derive from.
- abstract display_explanation(text: str) None
- Parameters
text – The text of an explanatory text (shown in normal font, wrapped if required). Different paragraphs are separated by repeated invocations of this method.
- class DisplayAsPlainText(display_text_func: Callable)
With this style, the output is simply returned in a plain manner. This is e.g. helpful when logging the text.
- display_explanation(text: str)
- Parameters
text – The text of an explanatory text (shown in normal font, wrapped if required). Different paragraphs are separated by repeated invocations of this method.
Exporting data
- class ExportContainerFlowManager
In the SQLite databases all data is stored. This might not be the right format for further usage though. This manager provides the interface to export the container flow, excluding the input distributions etc., so that they can be read in easily for the next step, e.g. a routine in a simulation model or mathematical optimization script.
- export(folder_name: str, path_to_export_folder: Optional[str] = None, file_format: Optional[ExportFileFormat] = None, overwrite: bool = False) str
This extracts the container movement data from the SQL database to a folder of choice in a tabular data format.
- Parameters
folder_name – Name of folder that bundles the tabular data which belongs together
path_to_export_folder – Path to directory where all exports are kept, defaults to
<project root>/data/exports/
file_format – Desired tabular format, defaults to
ExportFileFormat.csv
.overwrite – Whether to overwrite previously exported data, defaults to False
- Returns
The path to the folder where the tabular data is located
- enum ExportFileFormat(value)
The export file format supports tables. The export function enables the user to read in the generated synthetic data into another tool, such as a software for mathematical optimization or discrete event simulation.
Valid values are as follows:
- csv = <ExportFileFormat.csv: 'csv'>
Comma-separated values files are very simplistic representation but unrestricted and widely supported.
- xlsx = <ExportFileFormat.xlsx: 'xlsx'>
The xlsx file format can be opened by e.g. Microsoft Excel which might help to quickly analyse the output data. However, this file format comes with known limitations listed at https://support.microsoft.com/en-us/office/excel-specifications-and-limits-1672b34d-7043-467e-8e27-269d656771c3. On January 4th, 2022, the known maximum number of rows is 1,048,576. Thus, if e.g. 1.1 million containers are generated, opening this xlsx file in Excel is not supported by the specifications.
- xls = <ExportFileFormat.xls: 'xls'>
The xls format is the precursor of the xlsx format. This should only be used if a software demands this file format. Older versions of Excel had more restrictions on the size, e.g. Excel 2003 is known to have only supported 65,536 rows (see e.g. http://web.archive.org/web/20140819001409/http://news.office-watch.com/t/n.aspx?articleid=1408&zoneid=9) which is less than what large terminals nowadays handle within a month. Even with a hypothetical TEU factor of 2, this only reaches 1,572,864 TEU throughput per year.