diff --git a/activitysim/abm/models/trip_matrices.py b/activitysim/abm/models/trip_matrices.py index 2bc3d9f53..8d46e510b 100644 --- a/activitysim/abm/models/trip_matrices.py +++ b/activitysim/abm/models/trip_matrices.py @@ -26,7 +26,6 @@ class MatrixTableSettings(PydanticReadable): class MatrixSettings(PydanticReadable): file_name: Path tables: list[MatrixTableSettings] = [] - is_tap: bool = False class WriteTripMatricesSettings(PydanticReadable): @@ -62,9 +61,7 @@ def write_trip_matrices( then aggregates trip counts and writes OD matrices to OMX. Save annotated trips table to pipeline if desired. - Writes taz trip tables for one and two zone system. Add ``is_tap:True`` to - the settings file to identify an output matrix as tap level trips as opposed - to taz level trips. + Writes taz trip tables for one and two zone system. For one zone system, uses the land use table for the set of possible tazs. For two zone system, uses the taz skim zone names for the set of possible @@ -351,7 +348,6 @@ def write_matrices( orig_index, dest_index, model_settings: WriteTripMatricesSettings, - is_tap=False, ): """ Write aggregated trips to OMX format. @@ -371,42 +367,40 @@ def write_matrices( logger.error("Missing MATRICES setting in write_trip_matrices.yaml") for matrix in matrix_settings: - matrix_is_tap = matrix.is_tap - - if matrix_is_tap == is_tap: # only write tap matrices to tap matrix files - filename = str(matrix.file_name) - filepath = state.get_output_file_path(filename) - logger.info("opening %s" % filepath) - file = omx.open_file(str(filepath), "w") # possibly overwrite existing file - table_settings = matrix.tables - - for table in table_settings: - table_name = table.name - col = table.data_field - - if col not in aggregate_trips: - logger.error(f"missing {col} column in aggregate_trips DataFrame") - return - - hh_weight_col = model_settings.HH_EXPANSION_WEIGHT_COL - if hh_weight_col: - aggregate_trips[col] = ( - aggregate_trips[col] / aggregate_trips[hh_weight_col] - ) - - data = np.zeros((len(zone_index), len(zone_index))) - data[orig_index, dest_index] = aggregate_trips[col] - logger.debug( - "writing %s sum %0.2f" % (table_name, aggregate_trips[col].sum()) + + filename = str(matrix.file_name) + filepath = state.get_output_file_path(filename) + logger.info("opening %s" % filepath) + file = omx.open_file(str(filepath), "w") # possibly overwrite existing file + table_settings = matrix.tables + + for table in table_settings: + table_name = table.name + col = table.data_field + + if col not in aggregate_trips: + logger.error(f"missing {col} column in aggregate_trips DataFrame") + return + + hh_weight_col = model_settings.HH_EXPANSION_WEIGHT_COL + if hh_weight_col: + aggregate_trips[col] = ( + aggregate_trips[col] / aggregate_trips[hh_weight_col] ) - file[table_name] = data # write to file - # include the index-to-zone map in the file - logger.info( - "adding %s mapping for %s zones to %s" - % (zone_index.name, zone_index.size, filename) + data = np.zeros((len(zone_index), len(zone_index))) + data[orig_index, dest_index] = aggregate_trips[col] + logger.debug( + "writing %s sum %0.2f" % (table_name, aggregate_trips[col].sum()) ) - file.create_mapping(zone_index.name, zone_index.to_numpy()) + file[table_name] = data # write to file + + # include the index-to-zone map in the file + logger.info( + "adding %s mapping for %s zones to %s" + % (zone_index.name, zone_index.size, filename) + ) + file.create_mapping(zone_index.name, zone_index.to_numpy()) - logger.info("closing %s" % filepath) - file.close() + logger.info("closing %s" % filepath) + file.close() diff --git a/activitysim/examples/placeholder_multiple_zone/scripts/two_zone_example_data.py b/activitysim/examples/placeholder_multiple_zone/scripts/two_zone_example_data.py index 20c7bccf5..3e9847e92 100644 --- a/activitysim/examples/placeholder_multiple_zone/scripts/two_zone_example_data.py +++ b/activitysim/examples/placeholder_multiple_zone/scripts/two_zone_example_data.py @@ -3,8 +3,8 @@ # Transform the TM1 TAZ-based model 25 zone inputs to a two-zone (MAZ and TAZ) set of inputs for software development. # # The 25 zones are downtown San Francisco and they are converted to 25 MAZs. -# MAZs 1,2,3,4 are small and adjacent and assigned TAZ 2 and TAP 10002. -# MAZs 13,14,15 are small and adjacent and as signed TAZ 14 and TAP 10014. +# MAZs 1,2,3,4 are small and adjacent and assigned TAZ 2. +# MAZs 13,14,15 are small and adjacent and as signed TAZ 14. # TAZs 1,3,4,13,15 are removed from the final data set. # # This script should work for the full TM1 example as well. diff --git a/activitysim/examples/placeholder_multiple_zone/two_zone_example_data.py b/activitysim/examples/placeholder_multiple_zone/two_zone_example_data.py index a6f5750a0..8ebdbc89c 100644 --- a/activitysim/examples/placeholder_multiple_zone/two_zone_example_data.py +++ b/activitysim/examples/placeholder_multiple_zone/two_zone_example_data.py @@ -3,8 +3,8 @@ # Transform the TM1 TAZ-based model 25 zone inputs to a two-zone (MAZ and TAZ) set of inputs for software development. # # The 25 zones are downtown San Francisco and they are converted to 25 MAZs. -# MAZs 1,2,3,4 are small and adjacent and assigned TAZ 2 and TAP 10002. -# MAZs 13,14,15 are small and adjacent and as signed TAZ 14 and TAP 10014. +# MAZs 1,2,3,4 are small and adjacent and assigned TAZ 2. +# MAZs 13,14,15 are small and adjacent and as signed TAZ 14. # TAZs 1,3,4,13,15 are removed from the final data set. # # This script should work for the full TM1 example as well. diff --git a/docs/core.rst b/docs/core.rst index 687e8f956..1350e1581 100644 --- a/docs/core.rst +++ b/docs/core.rst @@ -354,50 +354,6 @@ API .. automodule:: activitysim.core.timetable :members: -.. _transit_virtual_path_builder: - -Transit Virtual Path Builder ----------------------------- - -Transit virtual path builder (TVPB) for three zone system (see :ref:`multiple_zone_systems`) transit path utility calculations. -TAP to TAP skims and walk access and egress times between MAZs and TAPs are input to the -demand model. ActivitySim then assembles the total transit path utility based on the user specified TVPB -expression files for the respective components: - -* from MAZ to first boarding TAP + -* from first boarding to final alighting TAP + -* from alighting TAP to destination MAZ - -This assembling is done via the TVPB, which considers all the possible combinations of nearby boarding and alighting TAPs for each origin -destination MAZ pair and selects the user defined N best paths to represent the transit mode. After selecting N best paths, the logsum across -N best paths is calculated and exposed to the mode choice models and a random number is drawn and a path is chosen. The boarding TAP, -alighting TAP, and TAP to TAP skim set for the chosen path is saved to the chooser table. - -The initialize TVPB submodel (see :ref:`initialize_los`) pre-computes TAP to TAP total utilities for the user defined attribute_segments, -which are typically demographic segment (for example household income bin), time-of-day, and access/egress mode. This submodel can be -run in both single process and multiprocess mode, with single process excellent for development/debugging and multiprocess excellent -for application. ActivitySim saves the pre-calculated TAP to TAP total utilities to a memory mapped cache file for reuse by downstream models -such as tour mode choice. In tour mode choice, the pre-computed TAP to TAP total utilities for the attribute_segment, along with the -access and egress impedances, are used to evaluate the best N TAP pairs for each origin MAZ destination MAZ pair being evaluated. -Assembling the total transit path impedance and then picking the best N is quick since it is done in a de-duplicated manner within -each chunk of multiprocessed choosers. - -A model with TVPB can take considerably longer to run than a traditional TAZ based model since it does an order of magnitude more -calculations. Thus, it is important to be mindful of your approach to your network model as well, especially the number of TAPs -accessible to each MAZ, which is the key determinant of runtime. - -API -~~~ - -.. automodule:: activitysim.core.pathbuilder - :members: - - -Cache API -~~~~~~~~~ - -.. automodule:: activitysim.core.pathbuilder_cache - :members: .. _visualization: diff --git a/docs/users-guide/model_anatomy.rst b/docs/users-guide/model_anatomy.rst index d80db1777..3ebccf98f 100644 --- a/docs/users-guide/model_anatomy.rst +++ b/docs/users-guide/model_anatomy.rst @@ -52,7 +52,7 @@ indicators (e.g. skims), the model uses different spatial resolutions for differ modeling burden and model runtimes. The typical multiple zone system setup is a TAZ zone system for auto travel, a MAZ zone system for non-motorized travel, and optionally a transit access points (TAPs) zone system for transit. -The three versions of multiple zone systems are one-zone, two-zone, and three-zone. +The two versions of zone systems are one-zone and two-zone. * **One-zone**: This version is based on TM1 and supports only TAZs. All origins and destinations are represented at the TAZ level, and all skims including auto, transit, @@ -65,45 +65,17 @@ The three versions of multiple zone systems are one-zone, two-zone, and three-zo walk access and egress times with times specified in the MAZ file by transit mode. Careful pre-calculation of the assumed transit walk access and egress time by MAZ and transit mode is required depending on the network scenario. -* **Three-zone**: This version is based on the SANDAG generation of CT-RAMP models. - Origins and destinations are represented at the MAZ level. Impedance for walk or - bike all-the-way from the origin to the destination can be specified at the MAZ - level for close together origins and destinations, and at the TAZ level for further - origins and destinations, just like the two-zone system. TAZs are used for auto - times and costs. The difference between this system and the two-zone system is that - transit times and costs are represented between Transit Access Points (TAPs), which - are essentially dummy zones that represent transit stops or clusters of stops. - Transit skims are built between TAPs, since there are typically too many MAZs to - build skims between them. Often multiple sets of TAP to TAP skims (local bus only, - all modes, etc.) are created and input to the demand model for consideration. Walk - access and egress times are also calculated between the MAZ and the TAP, and total - transit path utilities are assembled from their respective components - from MAZ to - first boarding TAP, from first boarding to final alighting TAP, and from alighting - TAP to destination MAZ. .. caution:: - The ActivitySim consortium is moving away from the three-zone approach, in favor of - to the one- or two-zone approaches. The three-zone system has been removed as of version 1.5.2. + Historically, there was also a three-zone option. The three-zone system has been + removed as of version 1.5.2. Regions that have an interest in more precise transit and non-motorized forecasts may wish to adopt the two-zone approach, while other regions may adopt the one or two-zone approach. The microzone version requires coding households and land use at the microzone level. Typically an all-streets network is used for representation of non-motorized impedances. This requires a routable all-streets network, with centroids and connectors for -microzones. If the three-zone system is adopted, procedures need to be developed to -code TAPs from transit stops and populate the all-street network with TAP centroids -and centroid connectors. A model with transit virtual path building takes longer to -run than a traditional TAZ only model, but it provides a much richer framework for -transit modeling. - -.. note:: - The two and three zone system test examples are simple test examples developed from the TM1 example. To develop the two zone system - example, TM1 TAZs were labeled MAZs, each MAZ was assigned a TAZ, and MAZ to MAZ impedance files were created from the - TAZ to TAZ impedances. To develop the three zone example system example, the TM1 TAZ model was further transformed - so select TAZs also became TAPs and TAP to TAP skims and MAZ to TAP impedances files were created. While sufficient for - initial development, these examples were insufficient for validation and performance testing of the new software. As a result, - the :ref:`prototype_marin` example was created. - +microzones. .. _omx_skims :