Skip to content

Commit

Permalink
Merge branch 'pr/209' into feature/transshipment-upgrade
Browse files Browse the repository at this point in the history
# Conflicts:
#	conflowgen/tests/flow_generator/test_large_scheduled_vehicle_for_onward_transportation_manager.py
  • Loading branch information
shubhs-93 committed Aug 16, 2024
2 parents 1a81456 + 994628e commit 3315d63
Show file tree
Hide file tree
Showing 105 changed files with 2,229 additions and 748 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/installation-from-remote.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@ jobs:

- name: Install ConFlowGen
run: |
conda info
conda update conda
conda info
conda create -n test-install-conflowgen -c conda-forge conflowgen pytest
- name: Prepare tests
run: |
conda activate test-install-conflowgen
conda install pillow>=9.0
conda install -c conda-forge pillow>=9.0
- name: Run tests
run: |
Expand Down Expand Up @@ -66,6 +68,8 @@ jobs:
conda init bash
eval "$(conda shell.bash hook)"
conda info
conda update conda
conda info
conda activate base
conda create -n test-install-conflowgen -c conda-forge conflowgen pytest
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,4 @@ examples/Python_Script/databases/
# Ignore local changes as they happen with every execution. If something changes, the commit must be forced.
conflowgen/data/tools/
docs/notebooks/data/prepared_dbs/
.tools/
Empty file added .tools/.gitkeep
Empty file.
11 changes: 7 additions & 4 deletions conflowgen/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@
InboundAndOutboundVehicleCapacityAnalysis
from conflowgen.analyses.inbound_and_outbound_vehicle_capacity_analysis_report import \
InboundAndOutboundVehicleCapacityAnalysisReport
from conflowgen.analyses.inbound_to_outbound_vehicle_capacity_utilization_analysis import \
InboundToOutboundVehicleCapacityUtilizationAnalysis
from conflowgen.analyses.inbound_to_outbound_vehicle_capacity_utilization_analysis_report import \
InboundToOutboundVehicleCapacityUtilizationAnalysisReport
from conflowgen.analyses.outbound_to_inbound_vehicle_capacity_utilization_analysis import \
OutboundToInboundVehicleCapacityUtilizationAnalysis
from conflowgen.analyses.outbound_to_inbound_vehicle_capacity_utilization_analysis_report import \
OutboundToInboundVehicleCapacityUtilizationAnalysisReport
from conflowgen.analyses.container_flow_by_vehicle_type_analysis import ContainerFlowByVehicleTypeAnalysis
from conflowgen.analyses.container_flow_by_vehicle_type_analysis_report import \
ContainerFlowByVehicleTypeAnalysisReport
Expand All @@ -64,6 +64,9 @@
ContainerFlowVehicleTypeAdjustmentPerVehicleAnalysis
from conflowgen.analyses.container_flow_vehicle_type_adjustment_per_vehicle_analysis_report import \
ContainerFlowVehicleTypeAdjustmentPerVehicleAnalysisReport
from conflowgen.analyses.container_flow_by_vehicle_instance_analysis import ContainerFlowByVehicleInstanceAnalysis
from conflowgen.analyses.container_flow_by_vehicle_instance_analysis_report import (
ContainerFlowByVehicleInstanceAnalysisReport)

# Cache for analyses and previews
from conflowgen.data_summaries.data_summaries_cache import DataSummariesCache
Expand Down
8 changes: 5 additions & 3 deletions conflowgen/analyses/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
ContainerFlowAdjustmentByVehicleTypeAnalysisReport
from .container_flow_adjustment_by_vehicle_type_analysis_summary_report import \
ContainerFlowAdjustmentByVehicleTypeAnalysisSummaryReport
from .container_flow_by_vehicle_instance_analysis_report import ContainerFlowByVehicleInstanceAnalysisReport
from .container_flow_by_vehicle_type_analysis_report import ContainerFlowByVehicleTypeAnalysisReport
from .container_flow_vehicle_type_adjustment_per_vehicle_analysis_report import \
ContainerFlowVehicleTypeAdjustmentPerVehicleAnalysisReport
from .inbound_and_outbound_vehicle_capacity_analysis_report import InboundAndOutboundVehicleCapacityAnalysisReport
from .inbound_to_outbound_vehicle_capacity_utilization_analysis_report import \
InboundToOutboundVehicleCapacityUtilizationAnalysisReport
from .outbound_to_inbound_vehicle_capacity_utilization_analysis_report import \
OutboundToInboundVehicleCapacityUtilizationAnalysisReport
from .modal_split_analysis_report import ModalSplitAnalysisReport
from .quay_side_throughput_analysis_report import QuaySideThroughputAnalysisReport
from .truck_gate_throughput_analysis_report import TruckGateThroughputAnalysisReport
Expand All @@ -26,6 +27,7 @@
reports: typing.Iterable[typing.Type[AbstractReport]] = [
InboundAndOutboundVehicleCapacityAnalysisReport,
ContainerFlowByVehicleTypeAnalysisReport,
ContainerFlowByVehicleInstanceAnalysisReport,
ContainerFlowAdjustmentByVehicleTypeAnalysisReport,
ContainerFlowAdjustmentByVehicleTypeAnalysisSummaryReport,
ContainerFlowVehicleTypeAdjustmentPerVehicleAnalysisReport,
Expand All @@ -34,7 +36,7 @@
QuaySideThroughputAnalysisReport,
TruckGateThroughputAnalysisReport,
YardCapacityAnalysisReport,
InboundToOutboundVehicleCapacityUtilizationAnalysisReport
OutboundToInboundVehicleCapacityUtilizationAnalysisReport
]


Expand Down
14 changes: 9 additions & 5 deletions conflowgen/analyses/abstract_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,35 +98,39 @@ def _restrict_storage_requirement(selected_containers: ModelSelect, storage_requ
@staticmethod
def _restrict_container_delivered_by_vehicle_type(
selected_containers: ModelSelect, container_delivered_by_vehicle_type: typing.Any
) -> ModelSelect:
) -> (ModelSelect, list[ModeOfTransport]):
if hashable(container_delivered_by_vehicle_type) \
and container_delivered_by_vehicle_type in set(ModeOfTransport):
selected_containers = selected_containers.where(
Container.delivered_by == container_delivered_by_vehicle_type
)
list_of_vehicle_types = [container_delivered_by_vehicle_type]
else: # assume it is some kind of collection (list, set, ...)
selected_containers = selected_containers.where(
Container.delivered_by << container_delivered_by_vehicle_type
)
return selected_containers
list_of_vehicle_types = list(container_delivered_by_vehicle_type)
return selected_containers, list_of_vehicle_types

@staticmethod
def _restrict_container_picked_up_by_vehicle_type(
selected_containers: ModelSelect, container_picked_up_by_vehicle_type: typing.Any
) -> ModelSelect:
) -> (ModelSelect, list[ModeOfTransport]):
if container_picked_up_by_vehicle_type == "scheduled vehicles":
container_picked_up_by_vehicle_type = ModeOfTransport.get_scheduled_vehicles()

list_of_vehicle_types = container_picked_up_by_vehicle_type
if hashable(container_picked_up_by_vehicle_type) \
and container_picked_up_by_vehicle_type in set(ModeOfTransport):
selected_containers = selected_containers.where(
Container.picked_up_by == container_picked_up_by_vehicle_type
)
list_of_vehicle_types = [container_picked_up_by_vehicle_type]
else: # assume it is some kind of collection (list, set, ...)
selected_containers = selected_containers.where(
Container.picked_up_by << container_picked_up_by_vehicle_type
)
return selected_containers
list_of_vehicle_types = list(container_picked_up_by_vehicle_type)
return selected_containers, list_of_vehicle_types

@staticmethod
def _restrict_container_picked_up_by_initial_vehicle_type(
Expand Down
4 changes: 2 additions & 2 deletions conflowgen/analyses/container_dwell_time_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ def get_container_dwell_times(
)

if container_delivered_by_vehicle_type != "all":
selected_containers = self._restrict_container_delivered_by_vehicle_type(
selected_containers, vehicle_types = self._restrict_container_delivered_by_vehicle_type(
selected_containers, container_delivered_by_vehicle_type
)

if container_picked_up_by_vehicle_type != "all":
selected_containers = self._restrict_container_picked_up_by_vehicle_type(
selected_containers, vehicle_types = self._restrict_container_picked_up_by_vehicle_type(
selected_containers, container_picked_up_by_vehicle_type
)

Expand Down
125 changes: 125 additions & 0 deletions conflowgen/analyses/container_flow_by_vehicle_instance_analysis.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
from __future__ import annotations

import datetime
import typing

from peewee import ModelSelect

from conflowgen.data_summaries.data_summaries_cache import DataSummariesCache
from conflowgen.domain_models.container import Container
from conflowgen.domain_models.data_types.mode_of_transport import ModeOfTransport
from conflowgen.analyses.abstract_analysis import AbstractAnalysis
from conflowgen.descriptive_datatypes import VehicleIdentifier, FlowDirection


class ContainerFlowByVehicleInstanceAnalysis(AbstractAnalysis):
"""
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 :class:`.ContainerFlowByVehicleInstanceAnalysisReport`.
"""

@DataSummariesCache.cache_result
def get_container_flow_by_vehicle(
self,
vehicle_types: typing.Collection[ModeOfTransport] = (
ModeOfTransport.train,
ModeOfTransport.feeder,
ModeOfTransport.deep_sea_vessel,
ModeOfTransport.barge
),
start_date: typing.Optional[datetime.datetime] = None,
end_date: typing.Optional[datetime.datetime] = None,
) -> [
ModeOfTransport, typing.Dict[VehicleIdentifier, typing.Dict[FlowDirection, (int, int)]]
]:
"""
Args:
vehicle_types: A collection of vehicle types, e.g., passed as a :class:`list` or :class:`set`.
Only the vehicles that correspond to the provided vehicle type(s) are considered in the analysis.
start_date:
The earliest arriving container that is included. Consider all containers if :obj:`None`.
end_date:
The latest departing container that is included. Consider all containers if :obj:`None`.
Returns:
Grouped by vehicle type and vehicle instance, how many import, export, and transshipment containers are
unloaded and loaded (measured in TEU).
"""

container_flow_by_vehicle: typing.Dict[
ModeOfTransport, typing.Dict[VehicleIdentifier,
typing.Dict[FlowDirection, typing.Dict[str, int]]]] = {
vehicle_type: {}
for vehicle_type in ModeOfTransport
}

vehicle_identifier_cache = {}

selected_containers: ModelSelect = Container.select().where(
(Container.delivered_by.in_(vehicle_types) | Container.picked_up_by.in_(vehicle_types))
)

container: Container
for container in selected_containers:
if start_date and container.get_arrival_time() < start_date:
continue
if end_date and container.get_departure_time() > end_date:
continue

if container.delivered_by_large_scheduled_vehicle is not None: # if not transported by truck

if container.delivered_by_large_scheduled_vehicle not in vehicle_identifier_cache:
vehicle_id_inbound = VehicleIdentifier(
id=container.delivered_by_large_scheduled_vehicle.id,
mode_of_transport=container.delivered_by,
service_name=container.delivered_by_large_scheduled_vehicle.schedule.service_name,
vehicle_name=container.delivered_by_large_scheduled_vehicle.vehicle_name,
vehicle_arrival_time=container.get_arrival_time(),
)
vehicle_identifier_cache[container.delivered_by_large_scheduled_vehicle] = vehicle_id_inbound

vehicle_id_inbound = vehicle_identifier_cache[container.delivered_by_large_scheduled_vehicle]

if vehicle_id_inbound not in container_flow_by_vehicle[container.delivered_by]:
container_flow_by_vehicle[container.delivered_by][vehicle_id_inbound] = {
flow_direction: {
"inbound": 0,
"outbound": 0,
}
for flow_direction in FlowDirection
}
container_flow_by_vehicle[
container.delivered_by
][vehicle_id_inbound][container.flow_direction]["inbound"] += container.occupied_teu

if container.picked_up_by_large_scheduled_vehicle is not None: # if not transported by truck

if container.picked_up_by_large_scheduled_vehicle not in vehicle_identifier_cache:
vehicle_id_outbound = VehicleIdentifier(
id=container.picked_up_by_large_scheduled_vehicle.id,
mode_of_transport=container.picked_up_by,
service_name=container.picked_up_by_large_scheduled_vehicle.schedule.service_name,
vehicle_name=container.picked_up_by_large_scheduled_vehicle.vehicle_name,
vehicle_arrival_time=container.get_departure_time(),
)
vehicle_identifier_cache[container.picked_up_by_large_scheduled_vehicle] = vehicle_id_outbound

vehicle_id_outbound = vehicle_identifier_cache[container.picked_up_by_large_scheduled_vehicle]

if vehicle_id_outbound not in container_flow_by_vehicle[container.picked_up_by]:
container_flow_by_vehicle[container.picked_up_by][vehicle_id_outbound] = {
flow_direction: {
"inbound": 0,
"outbound": 0,
}
for flow_direction in FlowDirection
}
container_flow_by_vehicle[
container.picked_up_by][vehicle_id_outbound][container.flow_direction]["outbound"] += 1

for skipped_vehicle_type in set(ModeOfTransport) - set(vehicle_types):
assert len(container_flow_by_vehicle[skipped_vehicle_type]) == 0
del container_flow_by_vehicle[skipped_vehicle_type]

return container_flow_by_vehicle
Loading

0 comments on commit 3315d63

Please sign in to comment.