diff --git a/.github/workflows/core_tests.yml b/.github/workflows/core_tests.yml index 0c11dd5df..1afe9270a 100644 --- a/.github/workflows/core_tests.yml +++ b/.github/workflows/core_tests.yml @@ -206,7 +206,6 @@ jobs: matrix: region: - prototype_mtc - - prototype_arc - placeholder_psrc - prototype_marin - prototype_mtc_extended diff --git a/activitysim/abm/models/parking_location_choice.py b/activitysim/abm/models/parking_location_choice.py index 2c9b5097c..d594dcfa3 100644 --- a/activitysim/abm/models/parking_location_choice.py +++ b/activitysim/abm/models/parking_location_choice.py @@ -330,6 +330,10 @@ class ParkingLocationSettings(LogitComponentSettings, extra="forbid"): SEGMENTS: list[str] | None = None + AUTO_MODES: list[str] + """List of auto modes that use parking. AUTO_MODES are used in write_trip_matrices to make sure + parking locations are accurately represented in the output trip matrices.""" + @workflow.step def parking_location( diff --git a/activitysim/abm/models/trip_matrices.py b/activitysim/abm/models/trip_matrices.py index 12c2e4f6a..5552e3b00 100644 --- a/activitysim/abm/models/trip_matrices.py +++ b/activitysim/abm/models/trip_matrices.py @@ -13,6 +13,7 @@ from activitysim.core import config, expressions, los, workflow from activitysim.core.configuration.base import PreprocessorSettings, PydanticReadable from activitysim.core.configuration.logit import LogitComponentSettings +from activitysim.abm.models.parking_location_choice import ParkingLocationSettings logger = logging.getLogger(__name__) @@ -93,16 +94,35 @@ def write_trip_matrices( state.add_table("trips", trips_df) if "parking_location" in state.settings.models: - parking_settings = state.filesystem.read_model_settings( - "parking_location_choice.yaml" + parking_settings = ParkingLocationSettings.read_settings_file( + state.filesystem, + "parking_location_choice.yaml", ) - parking_taz_col_name = parking_settings["ALT_DEST_COL_NAME"] + parking_taz_col_name = parking_settings.ALT_DEST_COL_NAME + if ~(trips_df["trip_mode"].isin(parking_settings.AUTO_MODES)).any(): + logger.warning( + f"Parking location choice model is enabled, but none of {parking_settings.AUTO_MODES} auto modes found in trips table." + "See AUTO_MODES setting in parking_location_choice.yaml." + ) + if parking_taz_col_name in trips_df: - # TODO make parking zone negative, not zero, if not used + trips_df["true_origin"] = trips_df["origin"] + trips_df["true_destination"] = trips_df["destination"] + + # Get origin parking zone if vehicle not parked at origin + trips_df["origin_parking_zone"] = np.where( + (trips_df["tour_id"] == trips_df["tour_id"].shift(1)) + & trips_df["trip_mode"].isin(parking_settings.AUTO_MODES), + trips_df[parking_taz_col_name].shift(1), + -1, + ) + trips_df.loc[trips_df[parking_taz_col_name] > 0, "destination"] = trips_df[ parking_taz_col_name ] - # Also need address the return trip + trips_df.loc[trips_df["origin_parking_zone"] > 0, "origin"] = trips_df[ + "origin_parking_zone" + ] # write matrices by zone system type if network_los.zone_system == los.ONE_ZONE: # taz trips written to taz matrices @@ -269,6 +289,24 @@ def write_trip_matrices( True, ) + if "parking_location" in state.settings.models: + # Set trip origin and destination to be the actual location the person is and not where their vehicle is parked + trips_df["origin"] = trips_df["true_origin"] + trips_df["destination"] = trips_df["true_destination"] + del trips_df["true_origin"], trips_df["true_destination"] + if ( + network_los.zone_system == los.TWO_ZONE + or network_los.zone_system == los.THREE_ZONE + ): + trips_df["otaz"] = ( + state.get_table("land_use").reindex(trips_df["origin"]).TAZ.tolist() + ) + trips_df["dtaz"] = ( + state.get_table("land_use") + .reindex(trips_df["destination"]) + .TAZ.tolist() + ) + def annotate_trips( state: workflow.State,