Skip to content

Commit

Permalink
Merge pull request #3 from dhensle/flexible_ids_for_merge
Browse files Browse the repository at this point in the history
Flexible ids for merge
  • Loading branch information
dhensle authored Oct 27, 2022
2 parents 0b4a692 + 9d7b9aa commit 1e567dd
Show file tree
Hide file tree
Showing 13 changed files with 2,273 additions and 0 deletions.
162 changes: 162 additions & 0 deletions activitysim/abm/models/util/canonical_ids.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import pandas as pd
import re

from activitysim.core.util import reindex
from activitysim.core import config
from activitysim.core import pipeline
from activitysim.core import simulate
Expand Down Expand Up @@ -218,6 +219,167 @@ def determine_flavors_from_alts_file(
return flavors


def read_alts_file(file_name, set_index=None):
try:
alts = simulate.read_model_alts(file_name, set_index=set_index)
except RuntimeError:
logger.warning(f"Could not find file {file_name} to determine tour flavors.")
return pd.DataFrame()
return alts


def read_spec_file(file_name, set_index=None):
try:
alts = simulate.read_model_alts(file_name, set_index=set_index)
except RuntimeError:
logger.warning(f"Could not find file {file_name} to determine tour flavors.")
return pd.DataFrame()
return alts


def parse_tour_flavor_from_columns(columns, tour_flavor):
"""
determines the max number from columns if column name contains tour flavor
example: columns={'work1', 'work2'} -> 2
Parameters
----------
columns : list of str
tour_flavor : str
string subset that you want to find in columns
Returns
-------
int
max int found in columns with tour_flavor
"""
# below produces a list of numbers present in each column containing the tour flavor string
tour_numbers = [(re.findall(r"\d+", col)) for col in columns if tour_flavor in col]

# flatten list
tour_numbers = [int(item) for sublist in tour_numbers for item in sublist]

# find max
try:
max_tour_flavor = max(tour_numbers)
return max_tour_flavor
except ValueError:
# could not find a maximum integer for this flavor in the columns
return -1


def determine_mandatory_tour_flavors(mtf_settings, model_spec, default_flavors):
provided_flavors = mtf_settings.get("MANDATORY_TOUR_FLAVORS", None)

mandatory_tour_flavors = {
# hard code work and school tours
"work": parse_tour_flavor_from_columns(model_spec.columns, "work"),
"school": parse_tour_flavor_from_columns(model_spec.columns, "school"),
}

valid_flavors = (mandatory_tour_flavors["work"] >= 1) & (
mandatory_tour_flavors["school"] >= 1
)

if provided_flavors is not None:
if mandatory_tour_flavors != provided_flavors:
logger.warning(
"Specified tour flavors do not match alternative file flavors"
)
logger.warning(
f"{provided_flavors} does not equal {mandatory_tour_flavors}"
)
# use provided flavors if provided
return provided_flavors

if not valid_flavors:
# if flavors could not be parsed correctly and no flavors provided, return the default
logger.warning(
"Could not determine alts from alt file and no flavors were provided."
)
logger.warning(f"Using defaults: {default_flavors}")
return default_flavors

return mandatory_tour_flavors


def determine_non_mandatory_tour_max_extension(
model_settings, extension_probs, default_max_extension=2
):
provided_max_extension = model_settings.get("MAX_EXTENSION", None)

max_extension = parse_tour_flavor_from_columns(extension_probs.columns, "tour")

if provided_max_extension is not None:
if provided_max_extension != max_extension:
logger.warning(
"Specified non mandatory tour extension does not match extension probabilities file"
)
return provided_max_extension

if (max_extension >= 0) & isinstance(max_extension, int):
return max_extension

return default_max_extension


def determine_flavors_from_alts_file(
alts, provided_flavors, default_flavors, max_extension=0
):
"""
determines the max number from alts for each column containing numbers
example: alts={'index': ['alt1', 'alt2'], 'escort': [1, 2], 'othdisc': [3, 4]}
yelds -> {'escort': 2, 'othdisc': 4}
will return provided flavors if available
else, return default flavors if alts can't be groked
Parameters
----------
alts : pd.DataFrame
provided_flavors : dict
tour flavors provided by user in the model yaml
default_flavors : dict
default tour flavors to fall back on
max_extension : int
scale to increase number of tours accross all alternatives
Returns
-------
dict
tour flavors
"""
try:
flavors = {
c: int(alts[c].max() + max_extension)
for c in alts.columns
if all(alts[c].astype(str).str.isnumeric())
}
valid_flavors = all(
[(isinstance(flavor, str) & (num >= 0)) for flavor, num in flavors.items()]
) & (len(flavors) > 0)
except (ValueError, AttributeError):
valid_flavors = False

if provided_flavors is not None:
if flavors != provided_flavors:
logger.warning(
f"Specified tour flavors {provided_flavors} do not match alternative file flavors {flavors}"
)
# use provided flavors if provided
return provided_flavors

if not valid_flavors:
# if flavors could not be parsed correctly and no flavors provided, return the default
logger.warning(
"Could not determine alts from alt file and no flavors were provided."
)
logger.warning(f"Using defaults: {default_flavors}")
return default_flavors

return flavors


def canonical_tours():
"""
create labels for every the possible tour by combining tour_type/tour_num.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#,,,alt file for building tours even though simulation is simple_simulate not interaction_simulate
alt,eat,business,maint
no_subtours,0,0,0
eat,1,0,0
business1,0,1,0
maint,0,0,1
business2,0,2,0
eat_business,1,1,0
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#,,,,,alt file for building joint tours
alt,shopping,othmaint,eatout,social,othdiscr
0_tours,0,0,0,0,0
1_Shop,1,0,0,0,0
1_Main,0,1,0,0,0
1_Eat,0,0,1,0,0
1_Visit,0,0,0,1,0
1_Disc,0,0,0,0,1
2_SS,2,0,0,0,0
2_SM,1,1,0,0,0
2_SE,1,0,1,0,0
2_SV,1,0,0,1,0
2_SD,1,0,0,0,1
2_MM,0,2,0,0,0
2_ME,0,1,1,0,0
2_MV,0,1,0,1,0
2_MD,0,1,0,0,1
2_EE,0,0,2,0,0
2_EV,0,0,1,1,0
2_ED,0,0,1,0,1
2_VV,0,0,0,2,0
2_VD,0,0,0,1,1
2_DD,0,0,0,0,2
Loading

0 comments on commit 1e567dd

Please sign in to comment.