Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Multiple Zone Systems and Transit Virtual Path Building #362

Merged
merged 120 commits into from
Dec 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
120 commits
Select commit Hold shift + click to select a range
e48aa39
Merge pull request #1 from ActivitySim/master
bstabler Oct 31, 2019
5097ce8
Merge pull request #2 from ActivitySim/master
bstabler Oct 31, 2019
2e50281
estimation through atwork_subtour_mode_choice
toliwaga May 5, 2020
2298dd6
wayward print statement
toliwaga May 5, 2020
3299222
estimation does not drop zero_rows from evaled spec
toliwaga May 6, 2020
5d844d6
pycodestyle
toliwaga May 6, 2020
981627e
Tnc updates and notebooks (#18)
bstabler May 7, 2020
aca4e6b
move estimatin notebooks to example folder
toliwaga May 8, 2020
b14e36e
change import column drop list to keep list
toliwaga May 12, 2020
553215b
Some doc updates, including dropping parking location choice since it…
bstabler May 12, 2020
29cacac
Merge branch 'develop' of https://github.com/RSGInc/activitysim into …
bstabler May 12, 2020
d2faf1f
update estimation flow chart
bstabler May 12, 2020
5687f47
improved tracing of expression_values in eval_utilities
toliwaga May 13, 2020
3728707
Merge branch 'develop' of https://github.com/RSGInc/activitysim into …
toliwaga May 13, 2020
1035cd8
want_dest_choice_sample_tables setting
toliwaga May 14, 2020
c53cc77
no more stagger
toliwaga May 14, 2020
b05db7a
no more stagger
toliwaga May 14, 2020
535566d
low level mp logging
toliwaga May 15, 2020
957eb85
multiprocessing related logging and error checking
toliwaga May 17, 2020
5f5817f
TEST_SPAWN flag to short circuit skim loading for faster mp spawn tes…
toliwaga May 17, 2020
967a843
trip_destination handle all trips fail
toliwaga May 18, 2020
f4576c5
skim caching with numpy memmap to speed skim loading
toliwaga May 19, 2020
a909446
better chunking in vectorize_tour_scheduling
toliwaga May 20, 2020
09fd741
estimation build script and a minot mode choice expression fix
toliwaga May 21, 2020
32c96b7
fix bug in tour mod echoice expression util_DRIVE_LRF_number_of_trans…
toliwaga May 21, 2020
d35f496
estimation data folders and skim fixes
toliwaga May 29, 2020
f85d451
add template output folder
bstabler May 29, 2020
f2f004e
generalized skim loading and working legacy (other resources) example…
toliwaga Jun 3, 2020
29d841b
skims setting to support multi-zone
toliwaga Jun 4, 2020
dcef79f
update estimation notebooks to run examples
bstabler Jun 5, 2020
2ba102f
rename taz fields to zone
toliwaga Jun 5, 2020
e2eb025
validation_tables not needed
bstabler Jun 5, 2020
11b4d16
more minor taz naming cleanup
toliwaga Jun 5, 2020
3619da4
add how to create example setups
bstabler Jun 5, 2020
2ba82cb
refactor skim loading in NetworkLOS
toliwaga Jun 5, 2020
87a3abe
support multiple maz_to_maz files for 2 zone
toliwaga Jun 15, 2020
04129f7
maz sparse skims blending
toliwaga Jun 15, 2020
6a54f21
best_transit_path roughout
toliwaga Jun 19, 2020
955bf06
3 zone example tweaks
toliwaga Jun 23, 2020
65d82f2
Cli (#22)
Jul 8, 2020
56621e6
update estimation examples to use cli interface to better create exam…
bstabler Jul 9, 2020
8595b1d
Update tour_mode_choice.csv (#24)
albabnoor Jul 15, 2020
9b66ea2
save notebook with latest results with latest code
bstabler Jul 15, 2020
fc4eaf7
updated notebooks to work with the latest software
bstabler Jul 16, 2020
4a74f1e
Merge remote-tracking branch 'upstream/develop' into develop
bstabler Jul 16, 2020
e223349
increment to version 0.9.5
bstabler Jul 16, 2020
ea1ca40
TransitVirtualPathBuilder first cut - get_tvpb_logsum computes logsum…
toliwaga Jul 17, 2020
1080bb5
correct write trip matrices sampling expansion and add vehicle occupa…
bstabler Jul 20, 2020
c852dd8
add strategic plan git flow diagram original
bstabler Jul 24, 2020
0abca62
pycodestyle other resources
bstabler Jul 27, 2020
a1c52f2
correct notebook testing
bstabler Jul 27, 2020
8fb2ec9
small documentation formatting update
bstabler Jul 27, 2020
3b6fcf3
various documentation updates
bstabler Jul 28, 2020
a132342
add back files used for tests
bstabler Jul 28, 2020
25bf422
updates to documentation for phase 5 work except multiple zone systems
bstabler Jul 29, 2020
e628fea
Merge branch 'master' into multi_zone
toliwaga Aug 3, 2020
0383d80
tour_mode_choice logsums for 3-zone working for school and workplace …
toliwaga Aug 10, 2020
e118717
estimation integration updates #327
bstabler Aug 11, 2020
0654046
Merge branch 'develop' of https://github.com/ActivitySim/activitysim …
bstabler Aug 11, 2020
0799578
Merge branch 'ActivitySim-develop' into develop
bstabler Aug 11, 2020
dfb743d
drop module no longer needed
bstabler Aug 11, 2020
41ca8b6
z3 running all models, but with hacked trip_mode_choice (no coefficie…
toliwaga Aug 25, 2020
4218946
z3 running all models
toliwaga Aug 26, 2020
61e5d0f
merge develop
toliwaga Aug 26, 2020
560b95f
passing tests
toliwaga Sep 2, 2020
9b038c8
pcodestyle passes
toliwaga Sep 2, 2020
7d4a2c8
refactored test teardown
toliwaga Sep 3, 2020
bd59d12
tvpb tracing
toliwaga Sep 14, 2020
17475fc
tvpb tracing roughout
toliwaga Sep 16, 2020
cce048f
merge with develop
toliwaga Sep 16, 2020
6ebe0d7
build multizone test data before running test
toliwaga Sep 16, 2020
161b8d6
read_settings_file support include_settings
toliwaga Sep 17, 2020
0433f50
read_settings_file support include_settings
toliwaga Sep 17, 2020
6d594f2
move constants to configs yaml and expressions from abm.util to core
toliwaga Sep 21, 2020
937d5b2
tvpb estimate_chunk_overhead
toliwaga Sep 24, 2020
d7727ef
adaptive chunking
toliwaga Oct 1, 2020
ca27b44
fixed bug in trip scheduling when no trips in leg after iteration
toliwaga Oct 2, 2020
437a9fb
3 zone tap_tap uniquify
toliwaga Oct 15, 2020
462e3d5
tvpb TableCache
toliwaga Oct 23, 2020
ae899b6
tvpb TableCache - all fiiels
toliwaga Oct 23, 2020
f1a4e8f
3 zone with feather cache
toliwaga Oct 29, 2020
3a581ec
tidy up notes around creating the marin example
bstabler Oct 30, 2020
c82fa35
memmap skims
toliwaga Nov 6, 2020
b579c21
memmap skims
toliwaga Nov 6, 2020
fe72f3b
Merge branch 'multizone' of https://github.com/ActivitySim/activitysi…
toliwaga Nov 6, 2020
b262b1e
correct drive transit cost expression for miles/feet. Still need to …
bstabler Nov 6, 2020
440adde
Merge branch 'multizone' of https://github.com/ActivitySim/activitysi…
bstabler Nov 6, 2020
55f4ada
skim docstrings
toliwaga Nov 9, 2020
714556b
Merge branch 'multizone' of https://github.com/ActivitySim/activitysi…
toliwaga Nov 9, 2020
0dd315a
disable 3 zone tap_tap caching for traced taps
toliwaga Nov 10, 2020
c95ab48
initialize_los
toliwaga Nov 13, 2020
161509b
3 zone mp plumbing untested
toliwaga Nov 16, 2020
d9bdf00
THREE_ZONE tvpb multiprocessing tests and fixes
toliwaga Nov 20, 2020
5f1949f
THREE_ZONE tvpb multiprocessing tests and fixes
toliwaga Nov 21, 2020
9909c92
reanme core tvpb and cache modules
toliwaga Nov 21, 2020
95d3423
reanme core tvpb and cache modules
toliwaga Nov 21, 2020
28a8f80
util.iprod alias for np.prod with dtype int64
toliwaga Nov 22, 2020
bbe17c0
THREE_ZONE cache initialization bug bixes
toliwaga Nov 25, 2020
330424b
multizone bug fixes
Nov 27, 2020
97f5297
bugs
toliwaga Nov 27, 2020
6bf0745
multiprocessing mjultizone tweaks
toliwaga Nov 27, 2020
8af75f6
tvpb cacha\e as array
toliwaga Nov 29, 2020
dc9cb48
complain if apporting with more process than slice rows
toliwaga Nov 30, 2020
1a911ab
complain if apporting with more process than slice rows
toliwaga Nov 30, 2020
53e2f6a
chunk initialize_tvpb
toliwaga Nov 30, 2020
dd5d0f7
shorter trace file names because windows
toliwaga Dec 2, 2020
5634dfd
refactor pathbuilder sans DYNAMIC
toliwaga Dec 2, 2020
873010f
fix tour_scheduling_calc_row_size
toliwaga Dec 5, 2020
22e197d
fix multiprocess resume across mp step bug
toliwaga Dec 5, 2020
cfe5345
pycodestyle
toliwaga Dec 5, 2020
b5b9813
minor chunk cleanup
toliwaga Dec 7, 2020
8d26ad6
allow MemMapSkimFactory multiprocessing
toliwaga Dec 8, 2020
f5419f2
consolidate mtc and multizone configs
toliwaga Dec 14, 2020
4bc4efc
commit updated marin example config files
bstabler Dec 15, 2020
ca6874c
some more marin example config updates
bstabler Dec 17, 2020
d55d8bf
add validation summaries script
bstabler Dec 18, 2020
3a08dae
some additional marin example updates
bstabler Dec 19, 2020
2d78679
update example skim time period settings to align with tm1 (#360)
bstabler Dec 22, 2020
ffd6740
corrected skim time periods go in network_los.yaml now
bstabler Dec 22, 2020
e3943b5
resolve merge conflicts by taking the multizone branch versions
bstabler Dec 22, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ install:
- pip install .
- pip freeze
script:
# build 2 and 3 zone test data
- python activitysim/examples/example_multiple_zone/two_zone_example_data.py
- python activitysim/examples/example_multiple_zone/three_zone_example_data.py
- pycodestyle activitysim
- py.test --cov activitysim --cov-report term-missing
after_success:
Expand Down
4 changes: 2 additions & 2 deletions activitysim/abm/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def households_sample_size(settings, override_hh_ids):
if override_hh_ids is None:
return settings.get('households_sample_size', 0)
else:
return len(override_hh_ids)
return 0 if override_hh_ids is None else len(override_hh_ids)


@inject.injectable(cache=True)
Expand Down Expand Up @@ -79,7 +79,7 @@ def trace_od(settings):

@inject.injectable(cache=True)
def chunk_size(settings):
return int(settings.get('chunk_size', 0))
return int(settings.get('chunk_size', 0) or 0)


@inject.injectable(cache=True)
Expand Down
3 changes: 3 additions & 0 deletions activitysim/abm/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
from . import cdap
from . import free_parking
from . import initialize
from . import initialize_tours
from . import initialize_los
from . import joint_tour_composition
from . import joint_tour_destination
from . import joint_tour_frequency
Expand All @@ -28,3 +30,4 @@
from . import trip_purpose_and_destination
from . import trip_scheduling
from . import trip_matrices
from . import summarize
185 changes: 99 additions & 86 deletions activitysim/abm/models/accessibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,95 +10,99 @@
from activitysim.core import config
from activitysim.core import inject
from activitysim.core import pipeline
from activitysim.core import mem

from activitysim.core import los
from activitysim.core.pathbuilder import TransitVirtualPathBuilder

logger = logging.getLogger(__name__)


class AccessibilitySkims(object):
"""
Wrapper for skim arrays to facilitate use of skims by accessibility model

Parameters
----------
skims : 2D array
omx: open omx file object
this is only used to load skims on demand that were not preloaded
length: int
number of zones in skim to return in skim matrix
in case the skims contain additional external zones that should be trimmed out so skim
array is correct shape to match (flattened) O-D tiled columns in the od dataframe
transpose: bool
whether to transpose the matrix before flattening. (i.e. act as a D-O instead of O-D skim)
"""

def __init__(self, skim_dict, orig_zones, dest_zones, transpose=False):

omx_shape = skim_dict.skim_info['omx_shape']
logger.info("init AccessibilitySkims with %d dest zones %d orig zones omx_shape %s" %
(len(dest_zones), len(orig_zones), omx_shape, ))

assert len(orig_zones) <= len(dest_zones)
assert np.isin(orig_zones, dest_zones).all()
assert len(np.unique(orig_zones)) == len(orig_zones)
assert len(np.unique(dest_zones)) == len(dest_zones)

self.skim_dict = skim_dict
self.transpose = transpose

if omx_shape[0] == len(orig_zones) and skim_dict.offset_mapper.offset_series is None:
# no slicing required because whatever the offset_int, the skim data aligns with zone list
self.map_data = False
else:

if omx_shape[0] == len(orig_zones):
logger.debug("AccessibilitySkims - applying offset_mapper")

skim_index = list(range(omx_shape[0]))
orig_map = skim_dict.offset_mapper.map(orig_zones)
dest_map = skim_dict.offset_mapper.map(dest_zones)

# (we might be sliced multiprocessing)
# assert np.isin(skim_index, orig_map).all()

if np.isin(skim_index, dest_map).all():
# not using the whole skim matrix
logger.info("%s skim zones not in dest_map: %s" %
((~dest_map).sum(), np.ix_(~dest_map)))

self.map_data = True
self.orig_map = orig_map
self.dest_map = dest_map

def __getitem__(self, key):
"""
accessor to return flattened skim array with specified key
flattened array will have length length*length and will match tiled OD df used by assign

this allows the skim array to be accessed from expressions as
skim['DISTANCE'] or skim[('SOVTOLL_TIME', 'MD')]
"""

data = self.skim_dict.get(key).data

if self.transpose:
data = data.transpose()

if self.map_data:

# slice skim to include only orig rows and dest columns
# 2-d boolean slicing in numpy is a bit tricky
# data = data[orig_map, dest_map] # <- WRONG!
# data = data[orig_map, :][:, dest_map] # <- RIGHT
# data = data[np.ix_(orig_map, dest_map)] # <- ALSO RIGHT

data = data[self.orig_map, :][:, self.dest_map]

return data.flatten()
# class AccessibilitySkims(object):
# """
# Wrapper for skim arrays to facilitate use of skims by accessibility model
#
# Parameters
# ----------
# skims : 2D array
# omx: open omx file object
# this is only used to load skims on demand that were not preloaded
# length: int
# number of zones in skim to return in skim matrix
# in case the skims contain additional external zones that should be trimmed out so skim
# array is correct shape to match (flattened) O-D tiled columns in the od dataframe
# transpose: bool
# whether to transpose the matrix before flattening. (i.e. act as a D-O instead of O-D skim)
# """
#
# def __init__(self, skim_dict, orig_zones, dest_zones, transpose=False):
#
# logger.info(f"init AccessibilitySkims with {len(dest_zones)} dest zones {len(orig_zones)} orig zones")
#
# assert len(orig_zones) <= len(dest_zones)
# assert np.isin(orig_zones, dest_zones).all()
# assert len(np.unique(orig_zones)) == len(orig_zones)
# assert len(np.unique(dest_zones)) == len(dest_zones)
#
# self.skim_dict = skim_dict
# self.transpose = transpose
#
# num_skim_zones = skim_dict.get_skim_info('omx_shape')[0]
# if num_skim_zones == len(orig_zones) and skim_dict.offset_mapper.offset_series is None:
# # no slicing required because whatever the offset_int, the skim data aligns with zone list
# self.map_data = False
# else:
#
# logger.debug("AccessibilitySkims - applying offset_mapper")
#
# skim_index = list(range(num_skim_zones))
# orig_map = skim_dict.offset_mapper.map(orig_zones)
# dest_map = skim_dict.offset_mapper.map(dest_zones)
#
# # (we might be sliced multiprocessing)
# # assert np.isin(skim_index, orig_map).all()
#
# out_of_bounds = ~np.isin(skim_index, dest_map)
# # if out_of_bounds.any():
# # print(f"{(out_of_bounds).sum()} skim zones not in dest_map")
# # print(f"dest_zones {dest_zones}")
# # print(f"dest_map {dest_map}")
# # print(f"skim_index {skim_index}")
# assert not out_of_bounds.any(), \
# f"AccessibilitySkims {(out_of_bounds).sum()} skim zones not in dest_map: {np.ix_(out_of_bounds)[0]}"
#
# self.map_data = True
# self.orig_map = orig_map
# self.dest_map = dest_map
#
# def __getitem__(self, key):
# """
# accessor to return flattened skim array with specified key
# flattened array will have length length*length and will match tiled OD df used by assign
#
# this allows the skim array to be accessed from expressions as
# skim['DISTANCE'] or skim[('SOVTOLL_TIME', 'MD')]
# """
#
# data = self.skim_dict.get(key).data
#
# if self.transpose:
# data = data.transpose()
#
# if self.map_data:
# # slice skim to include only orig rows and dest columns
# # 2-d boolean slicing in numpy is a bit tricky
# # data = data[orig_map, dest_map] # <- WRONG!
# # data = data[orig_map, :][:, dest_map] # <- RIGHT
# # data = data[np.ix_(orig_map, dest_map)] # <- ALSO RIGHT
#
# data = data[self.orig_map, :][:, self.dest_map]
#
# return data.flatten()


@inject.step()
def compute_accessibility(accessibility, skim_dict, land_use, trace_od):
def compute_accessibility(accessibility, network_los, land_use, trace_od):

"""
Compute accessibility for each zone in land use file using expressions from accessibility_spec
Expand Down Expand Up @@ -143,8 +147,8 @@ def compute_accessibility(accessibility, skim_dict, land_use, trace_od):
# create OD dataframe
od_df = pd.DataFrame(
data={
'orig': np.repeat(np.asanyarray(accessibility_df.index), dest_zone_count),
'dest': np.tile(np.asanyarray(land_use_df.index), orig_zone_count)
'orig': np.repeat(orig_zones, dest_zone_count),
'dest': np.tile(dest_zones, orig_zone_count)
}
)

Expand All @@ -160,9 +164,16 @@ def compute_accessibility(accessibility, skim_dict, land_use, trace_od):
locals_d = {
'log': np.log,
'exp': np.exp,
'skim_od': AccessibilitySkims(skim_dict, orig_zones, dest_zones),
'skim_do': AccessibilitySkims(skim_dict, orig_zones, dest_zones, transpose=True)
'network_los': network_los,
}

skim_dict = network_los.get_default_skim_dict()
locals_d['skim_od'] = skim_dict.wrap('orig', 'dest').set_df(od_df)
locals_d['skim_do'] = skim_dict.wrap('dest', 'orig').set_df(od_df)

if network_los.zone_system == los.THREE_ZONE:
locals_d['tvpb'] = TransitVirtualPathBuilder(network_los)

if constants is not None:
locals_d.update(constants)

Expand All @@ -174,13 +185,15 @@ def compute_accessibility(accessibility, skim_dict, land_use, trace_od):
data.shape = (orig_zone_count, dest_zone_count) # (o,d)
accessibility_df[column] = np.log(np.sum(data, axis=1) + 1)

logger.info("{trace_label} added {len(results.columns} columns")

# - write table to pipeline
pipeline.replace_table("accessibility", accessibility_df)

if trace_od:

if not trace_od_rows.any():
logger.warning("trace_od not found origin = %s, dest = %s" % (trace_orig, trace_dest))
logger.warning(f"trace_od not found origin = {trace_orig}, dest = {trace_dest}")
else:

# add OD columns to trace results
Expand Down
Loading